Skip to content

Commit

Permalink
Add concrete tests for rpq algorithms
Browse files Browse the repository at this point in the history
Also rename TestCaseCFPQ -> CaseCFPQ and fix docs
  • Loading branch information
KubEF committed Aug 30, 2024
1 parent af2d12e commit 3ecf8c0
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 36 deletions.
36 changes: 18 additions & 18 deletions tests/autotests/cfpq_concrete_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from pyformlang.rsa import RecursiveAutomaton


class TestCaseCFPQ:
class CaseCFPQ:
"""
class that contains all information about test case
class that contains all information about test case for cfpq algorithms
"""

def __init__(self, graph: MultiDiGraph, query: CFG, actual_answer: set[tuple[int, int]],
Expand All @@ -23,8 +23,8 @@ def check_answer_cfg(self, function: Callable[
set[tuple[int, int]],
]):
"""
assertion function to algorithms with cfg
:param function: testing function (*hellings_based_cfpq* or *matrix_based_cfpq*)
assertion function for algorithms with cfg
:param function: the function under test (*hellings_based_cfpq* or *matrix_based_cfpq*)
:return: assertion
"""
actual_res = function(self.query, self.graph, self.start_nodes, self.final_nodes)
Expand All @@ -34,8 +34,8 @@ def check_answer_rsm(self, function: Callable[
[RecursiveAutomaton, MultiDiGraph, set[int], set[int]], set[tuple[int, int]]
], cfg_to_rsm: Callable[[CFG], RecursiveAutomaton]):
"""
assertion function to algorithms with rsm
:param function: testing function (*tensor_based_cfpq* or *gll_based_cfpq*)
assertion function for algorithms with rsm
:param function: the function under test (*tensor_based_cfpq* or *gll_based_cfpq*)
:param cfg_to_rsm: function that convert CFG to RecursiveAutomaton
:return: assertion
"""
Expand All @@ -49,62 +49,62 @@ def __str__(self):


CASES_CFPQ = [
TestCaseCFPQ(
CaseCFPQ(
point_graph,
CFG.from_text("S -> a"),
set()
),
TestCaseCFPQ(
CaseCFPQ(
point_graph,
CFG.from_text("S -> S a | $"),
{(1, 1)}
),
TestCaseCFPQ(
CaseCFPQ(
set_of_vertices_without_edges,
CFG.from_text("S -> S a | $"),
{(0, 0), (2, 2), (1, 1)}
),
TestCaseCFPQ(
CaseCFPQ(
b_graph,
CFG.from_text("S -> a"),
set()
),
TestCaseCFPQ(
CaseCFPQ(
b_graph,
CFG.from_text("S -> b"),
{(0, 1)}
),
TestCaseCFPQ(
CaseCFPQ(
b_graph,
CFG.from_text("S -> S b | $"),
{(0, 1), (0, 0), (1, 1)}
),
TestCaseCFPQ(
CaseCFPQ(
bbb_graph,
CFG.from_text("S -> S b b | $"),
{(0, 1), (0, 0), (0, 2), (1, 1), (1, 2), (1, 0), (2, 2), (2, 1), (2, 0)}
),
TestCaseCFPQ(
CaseCFPQ(
bab_graph,
CFG.from_text("S -> S a | S b | $"),
{(0, 1), (0, 0), (0, 2), (1, 1), (1, 2), (1, 0), (2, 2), (2, 1), (2, 0)}
),
TestCaseCFPQ(
CaseCFPQ(
baa_graph,
CFG.from_text("S -> a S b | $"),
{(0, 0), (1, 1), (1, 0)}
),
TestCaseCFPQ(
CaseCFPQ(
baa_graph,
CFG.from_text("S -> a S b | a b"),
{(0, 0), (1, 0)}
),
TestCaseCFPQ(
CaseCFPQ(
set_of_vertices_without_edges,
CFG.from_text("S -> $"),
{(0, 0), (2, 2), (1, 1)}
),
TestCaseCFPQ(
CaseCFPQ(
aaa_graph,
CFG.from_text("S -> a | S S"),
{(0, 1), (0, 0), (0, 2), (1, 1), (1, 2), (1, 0), (2, 2), (2, 1), (2, 0)}
Expand Down
2 changes: 1 addition & 1 deletion tests/autotests/graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@
(0, 1, {LABEL: 'a'}),
(1, 2, {LABEL: 'a'}),
(2, 0, {LABEL: 'a'})
])
])
86 changes: 86 additions & 0 deletions tests/autotests/rpq_concrete_cases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from typing import Callable

from graphs import *
from copy import copy
from helper import rpq_dict_to_set


class CaseRPQ:
"""
class that contains all information about test case for rpq algorithms
"""

def __init__(self, graph: MultiDiGraph, regex: str, actual_answer: set[tuple[int, int]],
start_nodes: set[int] = None, final_nodes: set[int] = None):
self.graph = copy(graph)
self.regex = copy(regex)
self.expected_answer = copy(actual_answer)
self.start_nodes = copy(start_nodes) if start_nodes else graph.nodes
self.final_nodes = copy(final_nodes) if final_nodes else graph.nodes

def check_answer_regex(self, function: Callable[[MultiDiGraph, set[int], set[int], str], list[tuple[int, int]]]):
"""
assertion function for algorithms with regex
:param function: the function under test (*tensor_based_rpq*)
:return: assertion
"""
assert set(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(
point_graph,
"a",
set()
),
CaseRPQ(
point_graph,
"a*",
{(1, 1)}
),
CaseRPQ(
set_of_vertices_without_edges,
"a*",
{(0, 0), (2, 2), (1, 1)}
),
CaseRPQ(
b_graph,
"a",
set()
),
CaseRPQ(
b_graph,
"b",
{(0, 1)}
),
CaseRPQ(
b_graph,
"b*",
{(0, 1), (0, 0), (1, 1)}
),
CaseRPQ(
bbb_graph,
"(b b)*",
{(0, 1), (0, 0), (0, 2), (1, 1), (1, 2), (1, 0), (2, 2), (2, 1), (2, 0)}
),
CaseRPQ(
bab_graph,
"(a | b)*",
{(0, 1), (0, 0), (0, 2), (1, 1), (1, 2), (1, 0), (2, 2), (2, 1), (2, 0)}
),
]
16 changes: 7 additions & 9 deletions tests/autotests/test_task03.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
import random
import itertools
from grammars_constants import REGEXES
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
from project.task3 import intersect_automata, AdjacencyMatrixFA
from project.task3 import intersect_automata, AdjacencyMatrixFA, tensor_based_rpq
except ImportError:
pytestmark = pytest.mark.skip("Task 3 is not ready to test!")

Expand All @@ -38,18 +39,15 @@ def test(self, regex_str1: str, regex_str2: str) -> None:
return
word_parts = random.choice(all_word_parts)
else:
index = random.randint(0, 2**9)
index = random.randint(0, 2 ** 9)
word_parts = next(itertools.islice(words, index, None))

word = map(lambda x: x.value, word_parts)

assert intersect_fa.accepts(word)


def test_tensor_based_rpq_exists():
try:
import project.task3

assert "tensor_based_rpq" in dir(project.task3)
except NameError:
assert False
class TestTensorBasedRPQ:
@pytest.mark.parametrize('case', CASES_RPQ)
def test_concrete_cases(self, case: CaseRPQ):
case.check_answer_regex(tensor_based_rpq)
7 changes: 7 additions & 0 deletions tests/autotests/test_task04.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pytest
from grammars_constants import REGEXES
from helper import generate_rnd_start_and_final, rpq_dict_to_set
from rpq_concrete_cases import CASES_RPQ, CaseRPQ

# Fix import statements in try block to run tests
try:
Expand All @@ -23,6 +24,12 @@ 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)

def test(self, graph, query) -> None:
start_nodes, final_nodes = generate_rnd_start_and_final(graph.copy())
fa = AdjacencyMatrixFA(
Expand Down
4 changes: 2 additions & 2 deletions tests/autotests/test_task06.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest
from grammars_constants import REGEXP_CFG, GRAMMARS
from rpq_template_test import rpq_cfpq_test, different_grammars_test
from cfpq_concrete_cases import TestCaseCFPQ, CASES_CFPQ
from cfpq_concrete_cases import CaseCFPQ, CASES_CFPQ

# Fix import statements in try block to run tests
try:
Expand All @@ -16,7 +16,7 @@

class TestHellingBasedCFPQ:
@pytest.mark.parametrize("case", CASES_CFPQ)
def test_concrete_cases(self, case: TestCaseCFPQ):
def test_concrete_cases(self, case: CaseCFPQ):
case.check_answer_cfg(hellings_based_cfpq)

@pytest.mark.parametrize("regex_str, cfg_list", REGEXP_CFG)
Expand Down
4 changes: 2 additions & 2 deletions tests/autotests/test_task07.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from grammars_constants import REGEXP_CFG, GRAMMARS, GRAMMARS_DIFFERENT
from helper import generate_rnd_start_and_final
from rpq_template_test import rpq_cfpq_test, different_grammars_test
from cfpq_concrete_cases import CASES_CFPQ, TestCaseCFPQ
from cfpq_concrete_cases import CASES_CFPQ, CaseCFPQ

# Fix import statements in try block to run tests
try:
Expand All @@ -19,7 +19,7 @@

class TestMatrixBasedCFPQ:
@pytest.mark.parametrize("case", CASES_CFPQ)
def test_concrete_cases(self, case: TestCaseCFPQ):
def test_concrete_cases(self, case: CaseCFPQ):
case.check_answer_cfg(matrix_based_cfpq)

@pytest.mark.parametrize("regex_str, cfg_list", REGEXP_CFG)
Expand Down
4 changes: 2 additions & 2 deletions tests/autotests/test_task08.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
different_grammars_test,
cfpq_algorithm_test,
)
from cfpq_concrete_cases import CASES_CFPQ, TestCaseCFPQ
from cfpq_concrete_cases import CASES_CFPQ, CaseCFPQ

# Fix import statements in try block to run tests
try:
Expand All @@ -24,7 +24,7 @@

class TestTensorBasedCFPQ:
@pytest.mark.parametrize("case", CASES_CFPQ)
def test_concrete_cases(self, case: TestCaseCFPQ):
def test_concrete_cases(self, case: CaseCFPQ):
case.check_answer_rsm(tensor_based_cfpq, cfg_to_rsm)

@pytest.mark.parametrize("regex_str, cfg_list", REGEXP_CFG)
Expand Down
4 changes: 2 additions & 2 deletions tests/autotests/test_task09.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
different_grammars_test,
cfpq_algorithm_test,
)
from cfpq_concrete_cases import TestCaseCFPQ, CASES_CFPQ
from cfpq_concrete_cases import CaseCFPQ, CASES_CFPQ

# Fix import statements in try block to run tests
try:
Expand All @@ -25,7 +25,7 @@

class TestGLLBasedCFPQ:
@pytest.mark.parametrize("case", CASES_CFPQ)
def test_concrete_cases(self, case: TestCaseCFPQ):
def test_concrete_cases(self, case: CaseCFPQ):
case.check_answer_rsm(gll_based_cfpq, cfg_to_rsm)

@pytest.mark.parametrize("regex_str, cfg_list", REGEXP_CFG)
Expand Down

0 comments on commit 3ecf8c0

Please sign in to comment.