예제 #1
0
def generate_random_moore_machine(num_states,
                                  input_alphabet,
                                  output_alphabet,
                                  compute_prefixes=False) -> MooreMachine:
    """
    Generates a random Moore 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:

        Moore machine with num_states states

    """
    states = list()

    for i in range(num_states):
        states.append(MooreState(i, random.choice(output_alphabet)))

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

    mm = MooreMachine(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 moore_from_state_setup(state_setup) -> MooreMachine:
    """
    First state in the state setup is the initial state.
    Example state setup:
    state_setup = {
            "a": ("a", {"x": "b1", "y": "a"}),
            "b1": ("b", {"x": "b2", "y": "a"}),
            "b2": ("b", {"x": "b3", "y": "a"}),
            "b3": ("b", {"x": "b4", "y": "a"}),
            "b4": ("b", {"x": "c", "y": "a"}),
            "c": ("c", {"x": "a", "y": "a"}),
        }

    Args:

        state_setup: map from state_id to tuple(output and transitions_dict)

    Returns:

        Moore machine
    """

    # build states with state_id and output
    states = {key: MooreState(key, val[0]) for key, val in state_setup.items()}

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

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

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

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

    return mm
예제 #3
0
    def gen_moore_from_state_setup(state_setup) -> MooreMachine:
        # state_setup shoud map from state_id to tuple(output and transitions_dict)

        # build states with state_id and output
        states = {
            key: MooreState(key, val[0])
            for key, val in state_setup.items()
        }

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

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

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

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

        return mm
예제 #4
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