diff --git a/tasks.md b/tasks.md index 00f4d05c0..64077255a 100644 --- a/tasks.md +++ b/tasks.md @@ -57,7 +57,7 @@ Полный балл: 5 -- [ ] Реализовать тип (`AdjacencyMatrixFA`), представляющий конечный автомат в виде разреженной матрицы смежности из [sciPy](https://docs.scipy.org/doc/scipy/reference/sparse.html) (или сразу её булевой декомпозиции) и информации о стартовых и финальных вершинах. У типа должны быть конструкторы от `DeterministicFiniteAutomaton` и `NondeterministicFiniteAutomaton` из [Задачи 2](#задача-2-построение-детерминированного-конечного-автомата-по-регулярному-выражению-и-недетерминированного-конечного-автомата-по-графу). +- [ ] Реализовать тип (`AdjacencyMatrixFA`), представляющий конечный автомат в виде разреженной матрицы смежности из [sciPy](https://docs.scipy.org/doc/scipy/reference/sparse.html) (или сразу её булевой декомпозиции) и информации о стартовых и финальных вершинах. У типа должны быть статические методы `from_dfa` и `from_nfa` для инициализации от `DeterministicFiniteAutomaton` и `NondeterministicFiniteAutomaton` из [Задачи 2](#задача-2-построение-детерминированного-конечного-автомата-по-регулярному-выражению-и-недетерминированного-конечного-автомата-по-графу). - [ ] Реализовать функцию-интерпретатор для типа `AdjacencyMatrixFA`, выясняющую, принимает ли автомат заданную строку и является ли язык, задающийся автоматом, пустым. Для реализации последней функции рекомендуется использовать транзитивное замыкание матрицы смежности. - Требуемые функции: ```python @@ -76,8 +76,8 @@ - [ ] На основе предыдущей функции реализовать **функцию** выполнения регулярных запросов к графам: по графу с заданными стартовыми и финальными вершинами и регулярному выражению вернуть те пары вершин из заданных стартовых и финальных, которые связанны путём, формирующем слово из языка, задаваемого регулярным выражением. - Требуемая функция: ```python - def tensor_based_rpq(graph: MultiDiGraph, start_nodes: set[int], - final_nodes: set[int], regex:str) -> list[tuple[NodeView, NodeView]]: + def tensor_based_rpq(regex: str, graph: MultiDiGraph, start_nodes: set[int], + final_nodes: set[int]) -> set[tuple[int, int]]: pass ``` @@ -93,8 +93,8 @@ - Для каждой из стартовых вывести множество достижимых из неё. - Требуемая функция: ```python - def ms_bfs_based_rpq(fa: AdjacencyMatrixFA, - constraints_fa: AdjacencyMatrixFA) -> dict[int, set[int]]: + def ms_bfs_based_rpq(regex: str, graph: MultiDiGraph, start_nodes: set[int], + final_nodes: set[int]) -> set[tuple[int, int]]: pass ``` - [ ] Добавить собственные тесты при необходимости. diff --git a/tests/autotests/helper.py b/tests/autotests/helper.py index ca7f172a2..143e542d6 100644 --- a/tests/autotests/helper.py +++ b/tests/autotests/helper.py @@ -41,14 +41,6 @@ def generate_rnd_start_and_final(graph: nx.MultiDiGraph) -> tuple[set[int], set[ return start_nodes, final_nodes -def rpq_dict_to_set(rpq: dict[int, set[int]]) -> set[tuple[int, int]]: - rpq_set = set() - for node_from, nodes_to in rpq.items(): - for node_to in nodes_to: - rpq_set.add((node_from, node_to)) - return rpq_set - - class GraphWordsHelper: graph = None final_nodes = None diff --git a/tests/autotests/rpq_concrete_cases.py b/tests/autotests/rpq_concrete_cases.py index 2027891f6..3f1199146 100644 --- a/tests/autotests/rpq_concrete_cases.py +++ b/tests/autotests/rpq_concrete_cases.py @@ -28,7 +28,7 @@ def __init__( def check_answer_regex( self, function: Callable[ - [MultiDiGraph, set[int], set[int], str], list[tuple[int, int]] + [MultiDiGraph, set[int], set[int], str], set[tuple[int, int]] ], ): """ @@ -37,32 +37,10 @@ def check_answer_regex( :return: assertion """ assert ( - set(function(self.graph, self.start_nodes, self.final_nodes, self.regex)) + function(self.graph, self.start_nodes, self.final_nodes, self.regex) == self.expected_answer ) - def check_answer_automata( - self, - function, - fa, - constraints_fa, - ): - """ - assertion function for algorithms with automata - :param function: the function under test (*ms_bfs_based_rpq*) - :param fa: automata by graph - :param constraints_fa: automata by regex - :return: assertion - """ - assert rpq_dict_to_set(function(fa, constraints_fa)) == self.expected_answer - - def __str__(self): - return ( - f"expected result: {self.expected_answer}\n" - + f"regex: {self.regex}" - + f"graph: {self.graph.edges(data=True)}" - ) - CASES_RPQ = [ CaseRPQ(graphs.point_graph, "a", set()), diff --git a/tests/autotests/rpq_template_test.py b/tests/autotests/rpq_template_test.py index 7909e9043..f57e27a2a 100644 --- a/tests/autotests/rpq_template_test.py +++ b/tests/autotests/rpq_template_test.py @@ -1,13 +1,11 @@ from copy import deepcopy -from helper import generate_rnd_start_and_final, rpq_dict_to_set +from helper import generate_rnd_start_and_final from networkx import MultiDiGraph from pyformlang.cfg import CFG from pyformlang.rsa import RecursiveAutomaton from typing import Callable, Iterable try: - from project.task2 import graph_to_nfa, regex_to_dfa - from project.task3 import AdjacencyMatrixFA from project.task4 import ms_bfs_based_rpq except ImportError: pass @@ -27,12 +25,10 @@ def rpq_cfpq_test( cfpq: set[tuple[int, int]] = function( cf_gram, deepcopy(graph), start_nodes, final_nodes ) - rpq: set[tuple[int, int]] = rpq_dict_to_set( - ms_bfs_based_rpq( - AdjacencyMatrixFA(graph_to_nfa(graph, start_nodes, final_nodes)), - AdjacencyMatrixFA(regex_to_dfa(regex_str)), - ) + rpq: set[tuple[int, int]] = ms_bfs_based_rpq( + regex_str, deepcopy(graph), start_nodes, final_nodes ) + assert cfpq == rpq diff --git a/tests/autotests/test_task04.py b/tests/autotests/test_task04.py index 645133461..056b05438 100644 --- a/tests/autotests/test_task04.py +++ b/tests/autotests/test_task04.py @@ -6,13 +6,13 @@ from copy import deepcopy import pytest from grammars_constants import REGEXES -from helper import generate_rnd_start_and_final, rpq_dict_to_set +from helper import generate_rnd_start_and_final from rpq_concrete_cases import CASES_RPQ, CaseRPQ # Fix import statements in try block to run tests try: - from project.task2 import regex_to_dfa, graph_to_nfa - from project.task3 import tensor_based_rpq, AdjacencyMatrixFA + # from project.task2 import regex_to_dfa, graph_to_nfa + from project.task3 import tensor_based_rpq from project.task4 import ms_bfs_based_rpq except ImportError: pytestmark = pytest.mark.skip("Task 4 is not ready to test!") @@ -26,23 +26,15 @@ def query(request) -> str: class TestRPQ: @pytest.mark.parametrize("case", CASES_RPQ) def test_concrete_cases(self, case: CaseRPQ): - fa = AdjacencyMatrixFA( - graph_to_nfa(case.graph, case.start_nodes, case.final_nodes) - ) - constraint_fa = AdjacencyMatrixFA(regex_to_dfa(case.regex)) - case.check_answer_automata(ms_bfs_based_rpq, fa, constraint_fa) + case.check_answer_regex(ms_bfs_based_rpq) def test(self, graph, query) -> None: start_nodes, final_nodes = generate_rnd_start_and_final(graph.copy()) - fa = AdjacencyMatrixFA( - graph_to_nfa(deepcopy(graph), deepcopy(start_nodes), deepcopy(final_nodes)) - ) - constraint_fa = AdjacencyMatrixFA(regex_to_dfa(query)) - reachable = rpq_dict_to_set( - ms_bfs_based_rpq(deepcopy(fa), deepcopy(constraint_fa)) + ms_bfs = ms_bfs_based_rpq( + query, deepcopy(graph), deepcopy(start_nodes), deepcopy(final_nodes) ) - ends = tensor_based_rpq( - deepcopy(graph), deepcopy(start_nodes), deepcopy(final_nodes), query + tensor = tensor_based_rpq( + query, deepcopy(graph), deepcopy(start_nodes), deepcopy(final_nodes) ) - assert set(ends) == reachable + assert tensor == ms_bfs