Skip to content

Commit

Permalink
Унифицирование сигнатур функций rpq и cfpq (#166)
Browse files Browse the repository at this point in the history
* Change signatures of tasks 3 and 4

Also delete all not necessary functions

* Delete unused import

* Rewrite task 3 about constructor
  • Loading branch information
KubEF authored Sep 7, 2024
1 parent 3ff89ae commit 79445de
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 64 deletions.
11 changes: 5 additions & 6 deletions tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) (или сразу её булевой декомпозиции) и информации о стартовых и финальных вершинах. У типа должны быть конструктор от `DeterministicFiniteAutomaton` и `NondeterministicFiniteAutomaton` (первый является подклассом второго, так что можно не различать их явно) из [Задачи 2](#задача-2-построение-детерминированного-конечного-автомата-по-регулярному-выражению-и-недетерминированного-конечного-автомата-по-графу).
- [ ] Реализовать функцию-интерпретатор для типа `AdjacencyMatrixFA`, выясняющую, принимает ли автомат заданную строку и является ли язык, задающийся автоматом, пустым. Для реализации последней функции рекомендуется использовать транзитивное замыкание матрицы смежности.
- Требуемые функции:
```python
Expand All @@ -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
```

Expand All @@ -90,11 +90,10 @@

- [ ] Используя [разреженные матрицы из sciPy](https://docs.scipy.org/doc/scipy/reference/sparse.html) реализовать **функцию** достижимости с регулярными ограничениями с несколькими стартовыми вершинами (алгоритм на основе multiple source BFS через линейную алгебру).
- Для конструирования регулярного запроса и графа использовать [Задачи 2](#задача-2-построение-детерминированного-конечного-автомата-по-регулярному-выражению-и-недетерминированного-конечного-автомата-по-графу).
- Для каждой из стартовых вывести множество достижимых из неё.
- Требуемая функция:
```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
```
- [ ] Добавить собственные тесты при необходимости.
Expand Down
8 changes: 0 additions & 8 deletions tests/autotests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 2 additions & 25 deletions tests/autotests/rpq_concrete_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import graphs
from copy import copy
from helper import rpq_dict_to_set
from networkx import MultiDiGraph


Expand All @@ -28,7 +27,7 @@ def __init__(
def check_answer_regex(
self,
function: Callable[
[MultiDiGraph, set[int], set[int], str], list[tuple[int, int]]
[str, MultiDiGraph, set[int], set[int]], set[tuple[int, int]]
],
):
"""
Expand All @@ -37,32 +36,10 @@ def check_answer_regex(
:return: assertion
"""
assert (
set(function(self.graph, self.start_nodes, self.final_nodes, self.regex))
function(self.regex, self.graph, self.start_nodes, self.final_nodes)
== 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()),
Expand Down
12 changes: 4 additions & 8 deletions tests/autotests/rpq_template_test.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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


Expand Down
25 changes: 8 additions & 17 deletions tests/autotests/test_task04.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
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.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!")
Expand All @@ -26,23 +25,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

0 comments on commit 79445de

Please sign in to comment.