예제 #1
0
def generate_random_mealy_machine(num_states,
                                  input_alphabet,
                                  output_alphabet,
                                  compute_prefixes=False) -> MealyMachine:
    """
    Generates a random Mealy machine.

    Args:

        num_states: number of states
        input_alphabet: input alphabet
        output_alphabet: output alphabet
        compute_prefixes: if true, shortest path to reach each state will be computed (Default value = False)

    Returns:
        Mealy machine with num_states states

    """
    states = list()

    for i in range(num_states):
        states.append(MealyState(i))

    for state in states:
        for a in input_alphabet:
            state.transitions[a] = random.choice(states)
            state.output_fun[a] = random.choice(output_alphabet)

    mm = MealyMachine(states[0], states)
    if compute_prefixes:
        for state in states:
            state.prefix = mm.get_shortest_path(mm.initial_state, state)

    return mm
예제 #2
0
def mealy_from_state_setup(state_setup) -> MealyMachine:
    """
        First state in the state setup is the initial state.
        state_setup = {
            "a": {"x": ("o1", "b1"), "y": ("o2", "a")},
            "b1": {"x": ("o3", "b2"), "y": ("o1", "a")},
            "b2": {"x": ("o1", "b3"), "y": ("o2", "a")},
            "b3": {"x": ("o3", "b4"), "y": ("o1", "a")},
            "b4": {"x": ("o1", "c"), "y": ("o4", "a")},
            "c": {"x": ("o3", "a"), "y": ("o5", "a")},
        }


    Args:

        state_setup:
            state_setup should map from state_id to tuple(transitions_dict).

    Returns:

        Mealy Machine
    """
    # state_setup should map from state_id to tuple(transitions_dict).
    # Each entry in transition dict is <input> : <output, new_state_id>

    # build states with state_id and output
    states = {key: MealyState(key) for key, _ in state_setup.items()}

    # add transitions to states
    for state_id, state in states.items():
        for _input, (output, new_state) in state_setup[state_id].items():
            state.transitions[_input] = states[new_state]
            state.output_fun[_input] = output

    # states to list
    states = [state for state in states.values()]

    # build moore machine with first state as starting state
    mm = MealyMachine(states[0], states)

    for state in states:
        state.prefix = mm.get_shortest_path(mm.initial_state, state)

    return mm
예제 #3
0
    def gen_hypothesis(self, check_for_duplicate_rows=False) -> Automaton:
        """
        Generate automaton based on the values found in the observation table.
        :return:

        Args:

            check_for_duplicate_rows:  (Default value = False)

        Returns:

            Automaton of type `automaton_type`

        """
        state_distinguish = dict()
        states_dict = dict()
        initial_state = None
        automaton_class = {
            'dfa': Dfa,
            'mealy': MealyMachine,
            'moore': MooreMachine
        }

        # delete duplicate rows, only possible if no counterexample processing is present
        # counterexample processing removes the need for consistency check, as it ensures
        # that no two rows in the S set are the same
        if check_for_duplicate_rows:
            rows_to_delete = set()
            for i, s1 in enumerate(self.S):
                for s2 in self.S[i + 1:]:
                    if self.T[s1] == self.T[s2]:
                        rows_to_delete.add(s2)

            for row in rows_to_delete:
                self.S.remove(row)

        # create states based on S set
        stateCounter = 0
        for prefix in self.S:
            state_id = f's{stateCounter}'

            if self.automaton_type == 'dfa':
                states_dict[prefix] = DfaState(state_id)
                states_dict[prefix].is_accepting = self.T[prefix][0]
            elif self.automaton_type == 'moore':
                states_dict[prefix] = MooreState(state_id,
                                                 output=self.T[prefix][0])
            else:
                states_dict[prefix] = MealyState(state_id)

            states_dict[prefix].prefix = prefix
            state_distinguish[tuple(self.T[prefix])] = states_dict[prefix]

            if not prefix:
                initial_state = states_dict[prefix]
            stateCounter += 1

        # add transitions based on extended S set
        for prefix in self.S:
            for a in self.A:
                state_in_S = state_distinguish[self.T[prefix + a]]
                states_dict[prefix].transitions[a[0]] = state_in_S
                if self.automaton_type == 'mealy':
                    states_dict[prefix].output_fun[a[0]] = self.T[prefix][
                        self.E.index(a)]

        automaton = automaton_class[self.automaton_type](
            initial_state, list(states_dict.values()))
        automaton.characterization_set = self.E

        return automaton