def test_intersection_regex(self):
        """ Tests the intersection with a regex """
        # pylint: disable=too-many-locals
        state_p = State("p")
        state_q = State("q")
        state_r = State("r")
        state_i = Symbol("i")
        state_e = Symbol("e")
        state_z = StackSymbol("Z")
        state_x0 = StackSymbol("X0")
        pda = PDA(states={state_p, state_q, state_r},
                  input_symbols={state_i, state_e},
                  stack_alphabet={state_z, state_x0},
                  start_state=state_p,
                  start_stack_symbol=state_x0,
                  final_states={state_r})
        pda.add_transition(state_p, Epsilon(), state_x0, state_q,
                           [state_z, state_x0])
        pda.add_transition(state_q, state_i, state_z, state_q,
                           [state_z, state_z])
        pda.add_transition(state_q, state_e, state_z, state_q, [])
        pda.add_transition(state_q, Epsilon(), state_x0, state_r, [])

        state_s = finite_automaton.State("s")
        state_t = finite_automaton.State("t")
        i_dfa = finite_automaton.Symbol("i")
        e_dfa = finite_automaton.Symbol("e")
        dfa = finite_automaton.DeterministicFiniteAutomaton(
            states={state_s, state_t},
            input_symbols={i_dfa, e_dfa},
            start_state=state_s,
            final_states={state_s, state_t})
        dfa.add_transition(state_s, i_dfa, state_s)
        dfa.add_transition(state_s, e_dfa, state_t)
        dfa.add_transition(state_t, e_dfa, state_t)

        new_pda = pda.intersection(dfa)
        pda_es = new_pda.to_empty_stack()
        cfg = pda_es.to_cfg()
        self.assertEqual(new_pda.get_number_transitions(), 6)
        self.assertEqual(len(new_pda.states), 5)
        self.assertEqual(len(new_pda.final_states), 2)
        self.assertEqual(len(new_pda.input_symbols), 2)
        self.assertEqual(len(new_pda.stack_symbols), 2)

        i_cfg = Terminal("i")
        e_cfg = Terminal("e")

        self.assertTrue(cfg.contains([i_cfg, i_cfg, e_cfg, e_cfg, e_cfg]))

        new_pda = pda.intersection(
            finite_automaton.DeterministicFiniteAutomaton())
        self.assertEqual(new_pda.get_number_transitions(), 0)
Exemple #2
0
 def _process_to_enfa_when_no_son(self, s_from, s_to):
     if isinstance(self.head,
                   pyformlang.regular_expression.regex_objects.Epsilon):
         self._add_epsilon_transition_in_enfa_between(s_from, s_to)
     elif not isinstance(self.head,
                         pyformlang.regular_expression.regex_objects.Empty):
         symbol = finite_automaton.Symbol(self.head.value)
         self._enfa.add_transition(s_from, symbol, s_to)
Exemple #3
0
 def test_to_enfa0(self):
     """ Tests the transformation to a regex """
     symb_a = finite_automaton.Symbol("a")
     symb_b = finite_automaton.Symbol("b")
     symb_c = finite_automaton.Symbol("c")
     epsilon = finite_automaton.Epsilon()
     regex = Regex("a|b")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a]))
     self.assertTrue(enfa.accepts([symb_b]))
     self.assertFalse(enfa.accepts([symb_c]))
     self.assertFalse(enfa.accepts([epsilon]))
     self.assertFalse(enfa.accepts([symb_a, symb_b]))
     regex = Regex("a b")
     enfa = regex.to_epsilon_nfa()
     self.assertFalse(enfa.accepts([symb_a]))
     self.assertFalse(enfa.accepts([symb_b]))
     self.assertTrue(enfa.accepts([symb_a, symb_b]))
     regex = Regex("a b c")
     enfa = regex.to_epsilon_nfa()
     self.assertFalse(enfa.accepts([symb_a, symb_b]))
     self.assertTrue(enfa.accepts([symb_a, symb_b, symb_c]))
     self.assertFalse(enfa.accepts([symb_a, symb_b, symb_a]))
     regex = Regex("(a b)|c")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a, symb_b]))
     self.assertFalse(enfa.accepts([symb_a, symb_c]))
     self.assertFalse(enfa.accepts([symb_b, symb_c]))
     self.assertTrue(enfa.accepts([symb_c]))
     regex = Regex("")
     enfa = regex.to_epsilon_nfa()
     self.assertFalse(enfa.accepts([symb_a]))
     self.assertFalse(enfa.accepts([symb_b]))
     self.assertFalse(enfa.accepts([symb_c]))
     self.assertFalse(enfa.accepts([]))
     regex = Regex("a*")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a]))
     self.assertTrue(enfa.accepts([]))
     self.assertTrue(enfa.accepts([symb_a, symb_a]))
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_a]))
Exemple #4
0
 def test_to_enfa1(self):
     """ Tests the transformation to a regex """
     symb_a = finite_automaton.Symbol("a")
     symb_b = finite_automaton.Symbol("b")
     symb_c = finite_automaton.Symbol("c")
     regex = Regex("a**")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a]))
     self.assertTrue(enfa.accepts([]))
     self.assertTrue(enfa.accepts([symb_a, symb_a]))
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_a]))
     regex = Regex("a*b|c")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b]))
     self.assertTrue(enfa.accepts([symb_b]))
     self.assertTrue(enfa.accepts([symb_c]))
     self.assertFalse(enfa.accepts([symb_a, symb_a, symb_c]))
     regex = Regex("a*(b|c)")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b]))
     self.assertTrue(enfa.accepts([symb_b]))
     self.assertTrue(enfa.accepts([symb_c]))
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_c]))
     regex = Regex("a*.(b|c)")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b]))
     self.assertTrue(enfa.accepts([symb_b]))
     self.assertTrue(enfa.accepts([symb_c]))
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_c]))
     regex = Regex("a*.(b|c)epsilon")
     enfa = regex.to_epsilon_nfa()
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b]))
     self.assertTrue(enfa.accepts([symb_b]))
     self.assertTrue(enfa.accepts([symb_c]))
     self.assertTrue(enfa.accepts([symb_a, symb_a, symb_c]))
     regex = Regex("$")
     enfa = regex.to_epsilon_nfa()
     self.assertFalse(enfa.accepts([symb_a]))
     self.assertFalse(enfa.accepts([symb_b]))
     self.assertFalse(enfa.accepts([symb_c]))
     self.assertTrue(enfa.accepts([]))
Exemple #5
0
    def intersection(self, other: Any) -> "PDA":
        """ Gets the intersection of the current PDA with something else

        Equivalent to:
            >> pda and regex

        Parameters
        ----------
        other : any
            The other part of the intersection

        Returns
        ----------
        new_pda : :class:`~pyformlang.pda.PDA`
            The pda resulting of the intersection

        Raises
        ----------
        NotImplementedError
            When intersecting with something else than a regex or a finite
            automaton
        """
        if isinstance(other, Regex):
            other = other.to_epsilon_nfa().to_deterministic()
        elif isinstance(other, FiniteAutomaton):
            if not other.is_deterministic():
                other = other.to_deterministic()
        else:
            raise NotImplementedError
        start_state_other = other.start_states
        if len(start_state_other) == 0:
            return PDA()
        pda_state_converter = _PDAStateConverter(self._states, other.states)
        start_state_other = list(start_state_other)[0]
        final_state_other = other.final_states
        start = pda_state_converter.to_pda_combined_state(
            self._start_state, start_state_other)
        pda = PDA(start_state=start,
                  start_stack_symbol=self._start_stack_symbol)
        symbols = self._input_symbols.copy()
        symbols.add(Epsilon())
        to_process = [(self._start_state, start_state_other)]
        processed = {(self._start_state, start_state_other)}
        while to_process:
            state_in, state_dfa = to_process.pop()
            if (state_in in self._final_states
                    and state_dfa in final_state_other):
                pda.add_final_state(
                    pda_state_converter.to_pda_combined_state(
                        state_in, state_dfa))
            for symbol in symbols:
                if symbol == Epsilon():
                    symbol_dfa = finite_automaton.Epsilon()
                else:
                    symbol_dfa = finite_automaton.Symbol(symbol.value)
                if symbol == Epsilon():
                    next_states_dfa = [state_dfa]
                else:
                    next_states_dfa = other(state_dfa, symbol_dfa)
                if len(next_states_dfa) == 0:
                    continue
                for stack_symbol in self._stack_alphabet:
                    next_states_self = self._transition_function(
                        state_in, symbol, stack_symbol)
                    for next_state, next_stack in next_states_self:
                        for next_state_dfa in next_states_dfa:
                            pda.add_transition(
                                pda_state_converter.to_pda_combined_state(
                                    state_in, state_dfa), symbol, stack_symbol,
                                pda_state_converter.to_pda_combined_state(
                                    next_state, next_state_dfa), next_stack)
                            if (next_state, next_state_dfa) not in processed:
                                to_process.append((next_state, next_state_dfa))
                                processed.add((next_state, next_state_dfa))
        return pda
Exemple #6
0
    def intersection(self, other: Any) -> "PDA":
        """ Gets the intersection of the language L generated by the \
        current PDA when accepting by final state with something else
        
        Currently, it only works for regular languages (represented as \
        regular expressions or finite automata) as the intersection \
        between two PDAs is not context-free (it cannot be represented \
        with a PDA).

        Equivalent to:
            >> pda and regex

        Parameters
        ----------
        other : any
            The other part of the intersection

        Returns
        ----------
        new_pda : :class:`~pyformlang.pda.PDA`
            The pda resulting of the intersection

        Raises
        ----------
        NotImplementedError
            When intersecting with something else than a regex or a finite
            automaton
        """
        if isinstance(other, regular_expression.Regex):
            enfa = other.to_epsilon_nfa()
            other = enfa.to_deterministic()
        elif isinstance(other, FiniteAutomaton):
            is_deterministic = other.is_deterministic()
            if not is_deterministic:
                other = other.to_deterministic()
        else:
            raise NotImplementedError
        start_state_other = other.start_states
        if len(start_state_other) == 0:
            return PDA()
        pda_state_converter = _PDAStateConverter(self._states, other.states)
        start_state_other = list(start_state_other)[0]
        final_state_other = other.final_states
        start = pda_state_converter.to_pda_combined_state(self._start_state,
                                                          start_state_other)
        pda = PDA(start_state=start,
                  start_stack_symbol=self._start_stack_symbol)
        symbols = self._input_symbols.copy()
        symbols.add(Epsilon())
        to_process = [(self._start_state, start_state_other)]
        processed = {(self._start_state, start_state_other)}
        while to_process:
            state_in, state_dfa = to_process.pop()
            if (state_in in self._final_states and state_dfa in
                    final_state_other):
                pda.add_final_state(
                    pda_state_converter.to_pda_combined_state(state_in,
                                                              state_dfa))
            for symbol in symbols:
                if symbol == Epsilon():
                    symbol_dfa = finite_automaton.Epsilon()
                else:
                    symbol_dfa = finite_automaton.Symbol(symbol.value)
                if symbol == Epsilon():
                    next_states_dfa = [state_dfa]
                else:
                    next_states_dfa = other(state_dfa, symbol_dfa)
                if len(next_states_dfa) == 0:
                    continue
                for stack_symbol in self._stack_alphabet:
                    next_states_self = self._transition_function(state_in,
                                                                 symbol,
                                                                 stack_symbol)
                    for next_state, next_stack in next_states_self:
                        for next_state_dfa in next_states_dfa:
                            pda.add_transition(
                                pda_state_converter.to_pda_combined_state(
                                    state_in,
                                    state_dfa),
                                symbol,
                                stack_symbol,
                                pda_state_converter.to_pda_combined_state(
                                    next_state,
                                    next_state_dfa),
                                next_stack)
                            if (next_state, next_state_dfa) not in processed:
                                to_process.append((next_state, next_state_dfa))
                                processed.add((next_state, next_state_dfa))
        return pda