コード例 #1
0
    def test_to_graphviz(self):

        dfa = SimpleDFA(
            {"q0", "q1", "q2", "q3", "q4", "q5"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q0"},
            {},
        )

        dfa.to_graphviz()

        dfa = SimpleDFA(
            {"q0", "q1", "q2", "q3", "q4", "q5"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q3"},
            {
                "q0": {"a": "q0", "b": "q1"},
                "q1": {"a": "q0", "b": "q2"},
                "q2": {"a": "q3", "b": "q4"},
                "q3": {"a": "q3", "b": "q4"},
                "q4": {"a": "q3", "b": "q5"},
            },
        )

        dfa.to_graphviz()
コード例 #2
0
    def test_complete_when_dfa_is_not_complete(self):
        """Test that when we try to make complete a non-complete SimpleDFA
        then the returned SimpleDFA is complete."""

        dfa = SimpleDFA(
            {"q0", "q1"},
            MapAlphabet({"a", "b"}),
            "q0",
            set(),
            {"q0": {"a": "q0", "b": "q1"}},
        )

        expected_dfa = SimpleDFA(
            {"q0", "q1", "sink"},
            MapAlphabet({"a", "b"}),
            "q0",
            set(),
            {
                "q0": {"a": "q0", "b": "q1"},
                "q1": {"a": "sink", "b": "sink"},
                "sink": {"a": "sink", "b": "sink"},
            },
        )

        actual_dfa = dfa.complete()
        assert actual_dfa == expected_dfa
コード例 #3
0
    def test_reachable_no_transitions(self):
        """Test that the reachable SimpleDFA of a SimpleDFA without transitions
        is the SimpleDFA with only the initial state."""

        dfa = SimpleDFA({"q0", "q1", "q2"}, MapAlphabet({"a1", "a2"}), "q0", {"q1"}, {})

        actual_reachable_dfa = dfa.reachable()
        expected_reachable_dfa = SimpleDFA(
            {"q0"}, MapAlphabet({"a1", "a2"}), "q0", set(), {}
        )

        assert actual_reachable_dfa == expected_reachable_dfa
コード例 #4
0
    def test_coreachable_no_accepting_states_gives_empty_dfa(self):

        dfa = SimpleDFA(
            {"q0", "q1", "q2"},
            MapAlphabet({"a1", "a2"}),
            "q0",
            set(),
            {"q0": {"a1": "q0", "a2": "q1"}},
        )

        actual_coreachable = dfa.coreachable()

        expected_coreachable = EmptyDFA(MapAlphabet({"a1", "a2"}))

        assert actual_coreachable == expected_coreachable
コード例 #5
0
    def test_determinize(self):

        nfa = SimpleNFA(
            {"q0", "q1", "q2", "q3"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q3"},
            {
                "q0": {
                    "a": {"q1"}
                },
                "q1": {
                    "a": {"q0"},
                    "b": {"q2", "q1"}
                },
                "q2": {
                    "a": {"q2"},
                    "b": {"q3"}
                },
            },
        )

        actual_dfa = nfa.determinize().minimize().trim()

        assert not actual_dfa.accepts([])
        assert not actual_dfa.accepts(["a"])
        assert not actual_dfa.accepts(["b"])
        assert not actual_dfa.accepts(["a", "a"])
        assert not actual_dfa.accepts(["a", "b", "a"])
        assert not actual_dfa.accepts(["a", "a", "a", "b"])
        assert actual_dfa.accepts(["a", "a", "a", "b", "b", "a", "b"])
コード例 #6
0
ファイル: simple.py プロジェクト: whitemech/pythomata
    def __init__(
        self,
        states: Set[StateType],
        alphabet: AlphabetLike[SymbolType],
        initial_state: StateType,
        accepting_states: Set[StateType],
        transition_function: Dict[StateType, Dict[SymbolType, Set[StateType]]],
    ):
        """
        Initialize a NFA.

        :param states: the set of states.
        :param alphabet: the alphabet
        :param initial_state: the initial state
        :param accepting_states: the set of accepting states
        :param transition_function: the transition function
        """
        super().__init__()
        alphabet = (MapAlphabet(alphabet)
                    if not isinstance(alphabet, Alphabet) else alphabet)
        self._check_input(states, alphabet, initial_state, accepting_states,
                          transition_function)

        self._states = frozenset(states)  # type: FrozenSet[StateType]
        self._alphabet = alphabet  # type: Alphabet[SymbolType]
        self._initial_state = initial_state  # type: StateType
        self._accepting_states = frozenset(
            accepting_states)  # type: FrozenSet[StateType]
        self._transition_function = (
            transition_function
        )  # type: Dict[StateType, Dict[SymbolType, Set[StateType]]]

        self._build_indexes()
コード例 #7
0
 def test_some_accepting_states_not_in_states_raises_error(self):
     """Test that if some accepting states are not in the set of states we raise an error."""
     with pytest.raises(
             ValueError,
             match="Accepting states .* not in the set of states."):
         nfa = SimpleNFA({"q0", "q1"}, MapAlphabet({"a"}), "q0",
                         {"q2", "q3"}, {})
コード例 #8
0
    def test_coreachable_simple_case(self):

        dfa = SimpleDFA(
            {"q0", "q1", "q2"},
            MapAlphabet({"a1", "a2"}),
            "q0",
            {"q0"},
            {"q0": {"a1": "q0", "a2": "q1"}},
        )

        actual_coreachable = dfa.coreachable()

        expected_coreachable = SimpleDFA(
            {"q0"}, MapAlphabet({"a1", "a2"}), "q0", {"q0"}, {"q0": {"a1": "q0"}}
        )

        assert actual_coreachable == expected_coreachable
コード例 #9
0
 def setup_class(cls):
     """Set the test up."""
     cls.dfa = SimpleDFA(
         {0, 1, 2},
         MapAlphabet(["a", "b", "c"]),
         0,
         {2},
         {0: {"a": 0, "b": 1}, 1: {"b": 1, "c": 2}, 2: {"c": 2}},
     )
コード例 #10
0
 def test_is_complete_when_dfa_is_not_complete(self):
     """Test that the is_complete method return False if the SimpleDFA is not complete."""
     dfa = SimpleDFA(
         {"q0", "q1"},
         MapAlphabet({"a", "b"}),
         "q0",
         set(),
         {"q0": {"a": "q0", "b": "q1"}},
     )
     assert not dfa.is_complete()
コード例 #11
0
    def test_complete_when_dfa_is_already_complete(self):
        """Test that when we try to make complete an already complete SimpleDFA
        then the returned SimpleDFA is equal to the previous one."""

        complete_dfa = SimpleDFA(
            {"q"}, MapAlphabet({"a"}), "q", set(), {"q": {"a": "q"}}
        )

        new_dfa = complete_dfa.complete()
        assert complete_dfa == new_dfa
コード例 #12
0
ファイル: simple.py プロジェクト: whitemech/pythomata
def _extract_states_from_transition_function(
    transition_function: Dict, ) -> Tuple[Set[StateType], Alphabet]:
    """Extract states from a transition function."""
    states, symbols = set(), set()
    for start_state in transition_function:
        states.add(start_state)
        for symbol in transition_function[start_state]:
            end_state = transition_function[start_state][symbol]
            states.add(end_state)
            symbols.add(symbol)

    return states, MapAlphabet(symbols)
コード例 #13
0
ファイル: simple.py プロジェクト: whitemech/pythomata
def _extract_states_from_nondet_transition_function(transition_function):
    # type: (Dict) -> Tuple[Set[StateType], Alphabet]
    """Extract states from a non-deterministic transition function."""
    states, symbols = set(), set()
    for start_state in transition_function:
        states.add(start_state)
        for symbol in transition_function[start_state]:
            end_states = transition_function[start_state][symbol]
            states = states.union(end_states)
            symbols.add(symbol)

    return states, MapAlphabet(symbols)
コード例 #14
0
 def test_transition_function_with_invalid_symbols_raises_error(self):
     """Test that if a symbol of some transitions is invalid we raise an error."""
     with pytest.raises(
         ValueError,
         match="Transition function not valid: symbols .* are not in the alphabet.",
     ):
         SimpleDFA(
             {"q0", "q1"},
             MapAlphabet({"a"}),
             "q0",
             set(),
             {"q0": {"a": "q1"}, "q1": {"b": "q1"}},
         )
コード例 #15
0
    def test_trim_simple_case(self):
        dfa = SimpleDFA(
            {"q0", "q1", "q2", "sink"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q1"},
            {
                "q0": {"a": "q0", "b": "q1"},
                "q1": {"a": "sink", "b": "sink"},
                "sink": {"a": "sink", "b": "sink"},
            },
        )

        actual_trimmed_dfa = dfa.trim()

        expected_trimmed_dfa = SimpleDFA(
            {"q0", "q1"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q1"},
            {"q0": {"a": "q0", "b": "q1"}},
        )

        assert actual_trimmed_dfa == expected_trimmed_dfa
コード例 #16
0
 def test_transition_function_with_invalid_end_states_raises_error(self):
     """Test that if some of the ending states of the transitions is not in
      the set of states we raise an error."""
     with pytest.raises(
         ValueError,
         match="Transition function not valid: states .* "
         "are not in the set of states.",
     ):
         SimpleDFA(
             {"q0", "q1"},
             MapAlphabet({"a"}),
             "q0",
             set(),
             {"q0": {"a": "q1"}, "q1": {"a": "q2"}},
         )
コード例 #17
0
    def test_equality(self):
        """Test that the equality between two SimpleDFA works correctly."""
        assert self.dfa == self.dfa

        another_dfa = SimpleDFA(
            {0, 1, 2},
            MapAlphabet(["a", "b", "c"]),
            0,
            {2},
            {
                0: {"a": 0, "b": 1, "c": 2},
                1: {"a": 0, "b": 1, "c": 2},
                2: {"a": 0, "b": 1, "c": 2},
            },
        )
        assert self.dfa == another_dfa
コード例 #18
0
    def test_accepts(self):

        dfa = SimpleDFA(
            {"q0", "q1"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q1"},
            {"q0": {"a": "q0", "b": "q1"}},
        )

        assert not dfa.accepts([])
        assert not dfa.accepts(["a"])
        assert not dfa.accepts(["a"])
        assert dfa.accepts(["b"])
        assert dfa.accepts(["a", "b"])
        assert not dfa.accepts(["a", "a"])
        assert not dfa.accepts(["b", "b"])
コード例 #19
0
def test_dfa_from_transitions():
    """Test that the constructor "from_transitions" works correctly."""

    states = {"q0", "q1", "q2"}
    actions = MapAlphabet({"a0", "a1"})
    initial_state = "q0"
    final_states = {"q2"}
    transition_function = {"q0": {"a0": "q1"}, "q1": {"a1": "q2"}}

    expected_dfa = SimpleDFA(
        states, actions, initial_state, final_states, transition_function
    )

    actual_dfa = SimpleDFA.from_transitions(
        initial_state, final_states, transition_function
    )

    assert expected_dfa == actual_dfa
コード例 #20
0
 def test_transition_function_with_symbols_not_in_alphabet_raises_error(
         self):
     """Test that if a symbol of some transitions is not in the alphabet we raise an error."""
     with pytest.raises(
             ValueError,
             match=
             "Transition function not valid: some symbols are not in the alphabet.",
     ):
         nfa = SimpleNFA(
             {"q0", "q1"},
             MapAlphabet({"a"}),
             "q0",
             set(),
             {
                 "q0": {
                     "a": {"q1"}
                 },
                 "q1": {
                     "b": {"q1"}
                 }
             },
         )
コード例 #21
0
    def test_minimize(self):

        dfa = SimpleDFA(
            {"q0", "q1", "q2", "q3", "q4"},
            MapAlphabet({"a", "b", "c"}),
            "q0",
            {"q3", "q4"},
            {
                "q0": {"a": "q1", "b": "q2"},
                "q1": {"c": "q3"},
                "q2": {"c": "q3"},
                "q3": {"c": "q4"},
                "q4": {"c": "q4"},
            },
        )

        actual_minimized_dfa = dfa.minimize()

        # the renaming of the states is non deterministic, so we need to compare every substructure.
        assert len(actual_minimized_dfa._states) == 4
        assert actual_minimized_dfa._alphabet == ArrayAlphabet(["a", "b", "c"])
        assert actual_minimized_dfa.is_complete()
コード例 #22
0
    def test_level_to_accepting_states(self):
        dfa = SimpleDFA(
            {"q0", "q1", "q2", "q3", "q4", "q5"},
            MapAlphabet({"a", "b"}),
            "q0",
            {"q3"},
            {
                "q0": {"a": "q0", "b": "q1"},
                "q1": {"a": "q0", "b": "q2"},
                "q2": {"a": "q3", "b": "q4"},
                "q3": {"a": "q3", "b": "q4"},
                "q4": {"a": "q3", "b": "q5"},
            },
        )

        assert dfa.levels_to_accepting_states() == {
            "q0": 3,
            "q1": 2,
            "q2": 1,
            "q3": 0,
            "q4": 1,
            "q5": -1,
        }
コード例 #23
0
 def test_empty_set_of_states_raises_error(self):
     """Test that when we try to instantiate a DFA with an empty set of states we raise an error."""
     with pytest.raises(ValueError, match="The set of states cannot be empty."):
         SimpleDFA(set(), MapAlphabet({"a"}), "q0", set(), {})
コード例 #24
0
 def test_initial_state_not_in_states_raises_error(self):
     """Test that if the initial state is not in the set of states we raise an error."""
     with pytest.raises(
         ValueError, match="Initial state .* not in the set of states."
     ):
         SimpleDFA(set("q1"), MapAlphabet({"a"}), "q0", set(), {})
コード例 #25
0
 def test_is_complete_when_dfa_is_complete(self):
     """Test that the is_complete method return True if the SimpleDFA is complete."""
     dfa = SimpleDFA({"q"}, MapAlphabet({"a"}), "q", set(), {"q": {"a": "q"}})
     assert dfa.is_complete()