Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor types and names #299

Merged
merged 17 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions bindings/python/libmata/nfa/nfa.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "Mata::Nfa":
ctypedef umap[Symbol, StateSet] PostSymb
ctypedef umap[State, PostSymb] StateToPostMap
ctypedef umap[string, State] StringSubsetMap
ctypedef umap[string, State] StateNameMap
ctypedef umap[State, string] StateNameMap
ctypedef umap[State, State] StateRenaming
ctypedef umap[string, string] ParameterMap
Expand Down Expand Up @@ -69,6 +68,8 @@ cdef extern from "mata/nfa/nfa.hh" namespace "Mata::Nfa":
void remove(CTrans) except +
void remove(State, Symbol, State) except +
bool contains(State, Symbol, State)
COrdVector[CSymbolPost].const_iterator epsilon_symbol_posts(State state, Symbol epsilon)
COrdVector[CSymbolPost].const_iterator epsilon_symbol_posts(CStatePost& post, Symbol epsilon)

cdef cppclass CRun "Mata::Nfa::Run":
# Public Attributes
Expand Down Expand Up @@ -155,15 +156,13 @@ cdef extern from "mata/nfa/nfa.hh" namespace "Mata::Nfa":
vector[CTrans] get_transitions_to(State)
vector[CTrans] get_trans_as_sequence()
vector[CTrans] get_trans_from_as_sequence(State)
void trim(StateRenaming*)
CNfa& trim(StateRenaming*)
void get_one_letter_aut(CNfa&)
bool is_epsilon(Symbol)
CBoolVector get_useful_states()
StateSet get_reachable_states()
StateSet get_terminating_states()
void remove_epsilon(Symbol) except +
COrdVector[CSymbolPost].const_iterator get_epsilon_transitions(State state, Symbol epsilon)
COrdVector[CSymbolPost].const_iterator get_epsilon_transitions(CStatePost& post, Symbol epsilon)
void clear()
size_t size()

Expand Down Expand Up @@ -200,7 +199,7 @@ cdef extern from "mata/nfa/plumbing.hh" namespace "Mata::Nfa::Plumbing":
cdef void c_revert "Mata::Nfa::Plumbing::revert" (CNfa*, CNfa&)
cdef void c_remove_epsilon "Mata::Nfa::Plumbing::remove_epsilon" (CNfa*, CNfa&, Symbol) except +
cdef void c_minimize "Mata::Nfa::Plumbing::minimize" (CNfa*, CNfa&)
cdef void c_reduce "Mata::Nfa::Plumbing::reduce" (CNfa*, CNfa&, bool, StateRenaming*, ParameterMap&)
cdef void c_reduce "Mata::Nfa::Plumbing::reduce" (CNfa*, CNfa&, StateRenaming*, ParameterMap&)



Expand Down
28 changes: 15 additions & 13 deletions bindings/python/libmata/nfa/nfa.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ from libmata.nfa.nfa cimport \
from libmata.alphabets cimport CAlphabet
from libmata.utils cimport COrdVector, CBinaryRelation, BinaryRelation


cdef Symbol EPSILON = CEPSILON


def epsilon():
return EPSILON


cdef class Run:
"""Wrapper over the run in NFA."""
cdef mata_nfa.CRun *thisptr
Expand Down Expand Up @@ -492,8 +495,10 @@ cdef class Nfa:
Remove states which are not accessible (unreachable; state is accessible when the state is the endpoint of a path
starting from an initial state) or not co-accessible (non-terminating; state is co-accessible when the state is
the starting point of a path ending in a final state).
:return: Self.
"""
self.thisptr.get().trim(NULL)
return self

def trim_with_state_map(self):
"""Remove inaccessible (unreachable) and not co-accessible (non-terminating) states.
Expand All @@ -502,11 +507,11 @@ cdef class Nfa:
starting from an initial state) or not co-accessible (non-terminating; state is co-accessible when the state is
the starting point of a path ending in a final state).

:return: State map of original to new states.
:return: Self, State map of original to new states.
"""
cdef StateRenaming state_map
self.thisptr.get().trim(&state_map)
return {k: v for k, v in state_map}
return self, {k: v for k, v in state_map}

def get_one_letter_aut(self) -> Nfa:
"""Unify transitions to create a directed graph with at most a single transition between two states (using only
Expand Down Expand Up @@ -637,7 +642,6 @@ cdef class Nfa:
return_value = self.thisptr.get().post(input_states, symbol).ToVector()
return {v for v in return_value}


def remove_epsilon_inplace(self, Symbol epsilon = CEPSILON):
"""Removes transitions which contain epsilon symbol.

Expand All @@ -647,20 +651,20 @@ cdef class Nfa:
"""
self.thisptr.get().remove_epsilon(epsilon)

def get_epsilon_transitions(self, State state, Symbol epsilon = CEPSILON) -> SymbolPost | None:
def epsilon_symbol_posts(self, State state, Symbol epsilon = CEPSILON) -> SymbolPost | None:
"""Get epsilon transitions for a state.

:param state: State to get epsilon transitions for.
:param epsilon: Epsilon symbol.
:return: Epsilon transitions if there are any epsilon transitions for the passed state. None otherwise.
"""
cdef COrdVector[CSymbolPost].const_iterator c_epsilon_transitions_iter = self.thisptr.get().get_epsilon_transitions(
cdef COrdVector[CSymbolPost].const_iterator c_epsilon_symbol_posts_iter = self.thisptr.get().delta.epsilon_symbol_posts(
state, epsilon
)
if c_epsilon_transitions_iter == self.thisptr.get().delta.state_post(state).cend():
if c_epsilon_symbol_posts_iter == self.thisptr.get().delta.state_post(state).cend():
return None

cdef CSymbolPost epsilon_transitions = dereference(c_epsilon_transitions_iter)
cdef CSymbolPost epsilon_transitions = dereference(c_epsilon_symbol_posts_iter)
return SymbolPost(epsilon_transitions.symbol, epsilon_transitions.targets.ToVector())


Expand Down Expand Up @@ -861,38 +865,36 @@ def minimize(Nfa lhs):
mata_nfa.c_minimize(result.thisptr.get(), dereference(lhs.thisptr.get()))
return result

def reduce_with_state_map(Nfa aut, bool trim_input = True, params = None):
def reduce_with_state_map(Nfa aut, params = None):
"""Reduce the automaton.

:param Nfa aut: Original automaton to reduce.
:param bool trim_input: Whether to trim the input automaton first or not.
:param Dict params: Additional parameters for the reduction algorithm:
- "algorithm": "simulation"
:return: (Reduced automaton, state map of original to new states)
"""
params = params or {"algorithm": "simulation"}
cdef StateRenaming state_map
result = Nfa()
mata_nfa.c_reduce(result.thisptr.get(), dereference(aut.thisptr.get()), trim_input, &state_map,
mata_nfa.c_reduce(result.thisptr.get(), dereference(aut.thisptr.get()), &state_map,
{
k.encode('utf-8'): v.encode('utf-8') for k, v in params.items()
}
)

return result, {k: v for k, v in state_map}

def reduce(Nfa aut, bool trim_input = True, params = None):
def reduce(Nfa aut, params = None):
"""Reduce the automaton.

:param bool trim_input: Whether to trim the input automaton first or not.
:param Nfa aut: Original automaton to reduce.
:param Dict params: Additional parameters for the reduction algorithm:
- "algorithm": "simulation"
:return: Reduced automaton
"""
params = params or {"algorithm": "simulation"}
result = Nfa()
mata_nfa.c_reduce(result.thisptr.get(), dereference(aut.thisptr.get()), trim_input, NULL,
mata_nfa.c_reduce(result.thisptr.get(), dereference(aut.thisptr.get()), NULL,
{
k.encode('utf-8'): v.encode('utf-8') for k, v in params.items()
}
Expand Down
6 changes: 2 additions & 4 deletions bindings/python/libmata/nfa/strings.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ cdef extern from "mata/nfa/strings.hh" namespace "Mata::Strings::SegNfa":
EpsilonDepthTransitions get_epsilon_depths()
vector[CNfa] get_segments()

ctypedef vector[vector[shared_ptr[CNfa]]] NoodleSequence

cdef NoodleSequence c_noodlify "Mata::Strings::SegNfa::noodlify" (CNfa&, Symbol, bool)
cdef NoodleSequence c_noodlify_for_equation "Mata::Strings::SegNfa::noodlify_for_equation" \
cdef vector[vector[shared_ptr[CNfa]]] c_noodlify "Mata::Strings::SegNfa::noodlify" (CNfa&, Symbol, bool)
cdef vector[vector[shared_ptr[CNfa]]] c_noodlify_for_equation "Mata::Strings::SegNfa::noodlify_for_equation" \
(const vector[CNfa*]&, CNfa&, bool, ParameterMap&)
6 changes: 3 additions & 3 deletions bindings/python/libmata/nfa/strings.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cimport libmata.nfa.strings as mata_strings

from cython.operator import dereference, postincrement as postinc

from libmata.nfa.strings cimport NoodleSequence, CSegmentation
from libmata.nfa.strings cimport CSegmentation
from libmata.nfa.nfa cimport CTrans

cdef class Segmentation:
Expand Down Expand Up @@ -69,7 +69,7 @@ def noodlify(mata_nfa.Nfa aut, Symbol symbol, include_empty = False):
:return: List of automata: A list of all (non-empty) noodles.
"""
noodle_segments = []
cdef NoodleSequence c_noodle_segments = mata_strings.c_noodlify(
cdef vector[vector[shared_ptr[CNfa]]] c_noodle_segments = mata_strings.c_noodlify(
dereference(aut.thisptr.get()), symbol, include_empty
)
for c_noodle in c_noodle_segments:
Expand Down Expand Up @@ -121,7 +121,7 @@ def noodlify_for_equation(left_side_automata: list, mata_nfa.Nfa right_side_auto
c_left_side_automata.push_back((<mata_nfa.Nfa>lhs_aut).thisptr.get())
noodle_segments = []
params = params or {}
cdef NoodleSequence c_noodle_segments = mata_strings.c_noodlify_for_equation(
cdef vector[vector[shared_ptr[CNfa]]] c_noodle_segments = mata_strings.c_noodlify_for_equation(
c_left_side_automata, dereference(right_side_automaton.thisptr.get()), include_empty,
{
k.encode('utf-8'): v.encode('utf-8') if isinstance(v, str) else v
Expand Down
24 changes: 12 additions & 12 deletions bindings/python/tests/test_nfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ def test_reduce():
nfa = mata_nfa.Nfa()

# Test the reduction of an empty automaton.
result, state_map = mata_nfa.reduce_with_state_map(nfa, False)
result, state_map = mata_nfa.reduce_with_state_map(nfa)
assert result.get_num_of_trans() == 0
assert len(result.initial_states) == 0
assert len(result.final_states) == 0
Expand All @@ -904,15 +904,15 @@ def test_reduce():
nfa.add_state(2)
nfa.make_initial_state(1)
nfa.make_final_state(2)
result, state_map = mata_nfa.reduce_with_state_map(nfa, False)
result, state_map = mata_nfa.reduce_with_state_map(nfa)
assert result.get_num_of_trans() == 0
assert result.size() == 2
assert result.has_initial_state(state_map[1])
assert result.has_final_state(state_map[2])
assert state_map[1] == state_map[0]
assert state_map[2] != state_map[0]

result, state_map = mata_nfa.reduce_with_state_map(nfa, True)
result, state_map = mata_nfa.reduce_with_state_map(nfa.trim())
assert result.get_num_of_trans() == 0
assert result.size() == 0

Expand All @@ -936,7 +936,7 @@ def test_reduce():
nfa.add_transition(9, ord('c'), 0)
nfa.add_transition(0, ord('a'), 4)

result, state_map = mata_nfa.reduce_with_state_map(nfa, False)
result, state_map = mata_nfa.reduce_with_state_map(nfa)
assert result.size() == 6
assert result.has_initial_state(state_map[1])
assert result.has_initial_state(state_map[2])
Expand Down Expand Up @@ -1032,7 +1032,7 @@ def test_unify():
assert nfa.has_transition(10, 1, 2)


def test_get_epsilon_transitions():
def test_epsilon_symbol_posts():
nfa = mata_nfa.Nfa(10)
nfa.make_initial_state(0)
nfa.make_final_state(1)
Expand All @@ -1041,19 +1041,19 @@ def test_get_epsilon_transitions():
nfa.add_transition(1, 2, 2)
nfa.add_transition(1, mata_nfa.epsilon(), 2)
nfa.add_transition(1, mata_nfa.epsilon(), 3)
epsilon_transitions = nfa.get_epsilon_transitions(1)
assert epsilon_transitions.symbol == mata_nfa.epsilon()
assert epsilon_transitions.targets == [2, 3]
epsilon_symbol_posts = nfa.epsilon_symbol_posts(1)
assert epsilon_symbol_posts.symbol == mata_nfa.epsilon()
assert epsilon_symbol_posts.targets == [2, 3]

nfa.add_transition(0, 1, 2)
nfa.add_transition(0, 2, 2)
nfa.add_transition(0, 8, 5)
nfa.add_transition(0, 8, 6)
epsilon_transitions = nfa.get_epsilon_transitions(0, 8)
assert epsilon_transitions.symbol == 8
assert epsilon_transitions.targets == [5, 6]
epsilon_symbol_posts = nfa.epsilon_symbol_posts(0, 8)
assert epsilon_symbol_posts.symbol == 8
assert epsilon_symbol_posts.targets == [5, 6]

assert nfa.get_epsilon_transitions(5) is None
assert nfa.epsilon_symbol_posts(5) is None


def test_is_epsilon():
Expand Down
Loading