Exemple #1
0
def get_small_pomdp():
    from aalpy.automata import Mdp, MdpState

    q0 = MdpState("q0", "init")
    q1 = MdpState("q1", "beep")
    q2 = MdpState("q2", "beep")
    q3 = MdpState("q3", "coffee")
    q4 = MdpState("q4", "tea")

    q0.transitions['but'].append((q0, 1))
    q0.transitions['coin'].append((q1, 0.8))
    q0.transitions['coin'].append((q2, 0.2))

    q1.transitions['coin'].append((q1, 1))
    q1.transitions['but'].append((q3, 1))

    q2.transitions['coin'].append((q2, 0.3))
    q2.transitions['coin'].append((q1, 0.7))
    q2.transitions['but'].append((q4, 1))

    q3.transitions['coin'].append((q3, 1))
    q3.transitions['but'].append((q3, 1))

    q4.transitions['coin'].append((q4, 1))
    q4.transitions['but'].append((q4, 1))

    return Mdp(q0, [q0, q1, q2, q3, q4])
Exemple #2
0
def smm_to_mdp_conversion(smm: StochasticMealyMachine):
    """
    Convert SMM to MDP.

    Args:
      smm: StochasticMealyMachine: SMM to convert

    Returns:

        equivalent MDP

    """
    inputs = smm.get_input_alphabet()
    mdp_states = []
    smm_state_to_mdp_state = dict()
    init_state = MdpState("0", "___start___")
    mdp_states.append(init_state)
    for s in smm.states:
        incoming_edges = defaultdict(list)
        incoming_outputs = set()
        for pre_s in smm.states:
            for i in inputs:
                incoming_edges[i] += filter(lambda t: t[0] == s,
                                            pre_s.transitions[i])
                incoming_outputs.update(map(lambda t: t[1], incoming_edges[i]))
        state_id = 0
        for o in incoming_outputs:
            new_state_id = s.state_id + str(state_id)
            state_id += 1
            new_state = MdpState(new_state_id, o)
            mdp_states.append(new_state)
            smm_state_to_mdp_state[(s.state_id, o)] = new_state

    for s in smm.states:
        mdp_states_for_s = {
            mdp_state
            for (s_id, o), mdp_state in smm_state_to_mdp_state.items()
            if s_id == s.state_id
        }
        for i in inputs:
            for outgoing_t in s.transitions[i]:
                target_smm_state = outgoing_t[0]
                output = outgoing_t[1]
                prob = outgoing_t[2]
                target_mdp_state = smm_state_to_mdp_state[(
                    target_smm_state.state_id, output)]
                for mdp_state in mdp_states_for_s:
                    mdp_state.transitions[i].append((target_mdp_state, prob))
                if s == smm.initial_state:
                    init_state.transitions[i].append((target_mdp_state, prob))
    return Mdp(init_state, mdp_states)
Exemple #3
0
def get_faulty_coffee_machine_MDP():
    q0 = MdpState("q0", "init")
    q1 = MdpState("q1", "beep")
    q2 = MdpState("q2", "coffee")

    q0.transitions['but'].append((q0, 1))
    q0.transitions['coin'].append((q1, 1))
    q1.transitions['but'].append((q0, 0.1))
    q1.transitions['but'].append((q2, 0.9))
    q1.transitions['coin'].append((q1, 1))
    q2.transitions['but'].append((q0, 1))
    q2.transitions['coin'].append((q1, 1))

    mdp = Mdp(q0, [q0, q1, q2])

    return mdp
Exemple #4
0
def generate_random_mdp(num_states,
                        len_input,
                        custom_outputs=None,
                        num_unique_outputs=None):
    """
    Generates random MDP.

    Args:

        num_states: number of states
        len_input: number of inputs
        custom_outputs: user predefined outputs
        num_unique_outputs: number of outputs

    Returns:

        random MDP

    """
    num_unique_outputs = num_states if not num_unique_outputs else num_unique_outputs
    outputs = [
        random_string_generator(random.randint(3, 7))
        for _ in range(num_unique_outputs)
    ]
    outputs = custom_outputs if custom_outputs else outputs

    while len(outputs) < num_states:
        outputs.append(random.choice(outputs))

    possible_probabilities = [1.0, 1.0, 1.0, 1.0, 0.8, 0.5, 0.9]
    states = []
    for i in range(num_states):
        states.append(MdpState(f'q{i}', outputs.pop()))

    for state in states:
        for i in range(len_input):
            prob = random.choice(possible_probabilities)
            if prob == 1.:
                state.transitions[i].append((random.choice(states), prob))
            else:
                new_states = list(states)
                s1 = random.choice(new_states)
                new_states.remove(s1)

                state.transitions[i].append((s1, prob))
                state.transitions[i].append(
                    (random.choice(new_states), round(1 - prob, 2)))

    return Mdp(states[0], states), list(range(len_input))
Exemple #5
0
def get_weird_coffee_machine_MDP():
    from aalpy.automata import Mdp, MdpState

    q0 = MdpState("q0", "init")
    q1 = MdpState("q1", "beep")
    q2 = MdpState("q2", "coffee")
    q3 = MdpState("q3", "beep")
    q4 = MdpState("q4", "coffee")
    q5 = MdpState("q5", "init")
    q6 = MdpState("q6", "crash")

    q0.transitions['but'].append((q0, 1))
    q0.transitions['coin'].append((q1, 1))
    q0.transitions['koin'].append((q3, 1))

    q1.transitions['but'].append((q0, 0.1))
    q1.transitions['but'].append((q2, 0.9))

    q3.transitions['but'].append((q0, 0.1))
    q3.transitions['but'].append((q4, 0.9))

    q1.transitions['coin'].append((q1, 1))
    q3.transitions['koin'].append((q3, 1))
    q1.transitions['koin'].append((q3, 1))
    q3.transitions['coin'].append((q1, 1))

    q2.transitions['but'].append((q0, 1))
    q2.transitions['coin'].append((q1, 1))
    q2.transitions['koin'].append((q3, 1))

    q4.transitions['coin'].append((q1, 1))
    q4.transitions['koin'].append((q3, 1))

    q4.transitions['but'].append((q5, 1))

    q5.transitions['but'].append((q6, 1))
    q5.transitions['coin'].append((q6, 1))
    q5.transitions['koin'].append((q6, 1))

    q6.transitions['but'].append((q6, 1))
    q6.transitions['coin'].append((q6, 1))
    q6.transitions['koin'].append((q6, 1))

    mdp = Mdp(q0, [q0, q1, q2, q3, q4, q5, q6])

    return mdp
Exemple #6
0
def to_mdp():
    eq_oracle = RandomWMethodEqOracle(alphabet, model_sul)

    learned_model = run_Lstar(alphabet, model_sul, eq_oracle, 'moore')

    # CC2640R2-no-feature-req.dot
    # {'mtu_req', 'pairing_req',} have 0.3 percent chance of looping to initial state
    moore_mdp_state_map = dict()
    initial_mdp_state = None
    for state in learned_model.states:
        mdp_state = MdpState(state.state_id, state.output)
        moore_mdp_state_map[state.prefix] = mdp_state
        if not state.prefix:
            initial_mdp_state = mdp_state

    # moore_mdp_state_map['sink'] = MdpState('sink', 'NO_RESPONSE')
    assert initial_mdp_state

    for state in learned_model.states:
        mdp_state = moore_mdp_state_map[state.prefix]
        state_num = int(mdp_state.state_id[1:])

        for i in alphabet:
            reached_moore = state.transitions[i].prefix
            # if i in {'pairing_req', 'mtu_req'} and mdp_state.output != moore_mdp_state_map[reached_moore].output:
            if state_num % 2 == 0 and mdp_state.output != moore_mdp_state_map[
                    reached_moore].output:
                mdp_state.transitions[i].append((mdp_state, 0.2))
                mdp_state.transitions[i].append(
                    (moore_mdp_state_map[reached_moore], 0.8))
            else:
                mdp_state.transitions[i].append(
                    (moore_mdp_state_map[reached_moore], 1.))

    mdp = Mdp(initial_mdp_state, list(moore_mdp_state_map.values()))
    return mdp
Exemple #7
0
    def generate_hypothesis(self):
        """Generates the hypothesis from the observation table.
        :return: current hypothesis

        Args:

        Returns:

        """
        r_state_map = dict()
        state_counter = 0
        for r in self.compatibility_classes_representatives:
            if self.automaton_type == 'mdp':
                r_state_map[r] = MdpState(state_id=f's{state_counter}', output=r[-1])
            else:
                r_state_map[r] = StochasticMealyState(state_id=f's{state_counter}')
            r_state_map[r].prefix = r

            state_counter += 1
        if self.automaton_type == 'mdp':
            r_state_map['chaos'] = MdpState(state_id=f's{state_counter}', output='chaos')
            for i in self.input_alphabet:
                r_state_map['chaos'].transitions[i[0]].append((r_state_map['chaos'], 1.))
        else:
            r_state_map['chaos'] = StochasticMealyState(state_id=f'chaos')
            for i in self.input_alphabet:
                r_state_map['chaos'].transitions[i[0]].append((r_state_map['chaos'], 'chaos', 1.))

        for s in self.compatibility_classes_representatives:
            for i in self.input_alphabet:
                freq_dict = self.T[s][i]

                total_sum = sum(freq_dict.values())

                origin_state = s
                if self.strategy == 'classic' and not self.teacher.complete_query(s, i) \
                        or self.strategy != 'classic' and i not in self.T[s]:
                    if self.automaton_type == 'mdp':
                        r_state_map[origin_state].transitions[i[0]].append((r_state_map['chaos'], 1.))
                    else:
                        r_state_map[origin_state].transitions[i[0]].append((r_state_map['chaos'], 'chaos', 1.))
                else:
                    if len(freq_dict.items()) == 0:
                        if self.automaton_type == 'mdp':
                            r_state_map[origin_state].transitions[i[0]].append((r_state_map['chaos'], 1.))
                        else:
                            r_state_map[origin_state].transitions[i[0]].append((r_state_map['chaos'], 'chaos', 1.))
                    else:
                        for output, frequency in freq_dict.items():
                            new_state = self.get_representative(s + i + tuple([output]))
                            if self.automaton_type == 'mdp':
                                r_state_map[origin_state].transitions[i[0]].append(
                                    (r_state_map[new_state], frequency / total_sum))
                            else:
                                r_state_map[origin_state].transitions[i[0]].append(
                                    (r_state_map[new_state], output, frequency / total_sum))

        if self.automaton_type == 'mdp':
            return Mdp(r_state_map[self.get_representative(self.initial_output)], list(r_state_map.values()))
        else:
            return StochasticMealyMachine(r_state_map[tuple()], list(r_state_map.values()))
Exemple #8
0
def generate_random_mdp(num_states,
                        input_size,
                        output_size,
                        possible_probabilities=None):
    """
    Generates random MDP.

    Args:

        num_states: number of states
        input_size: number of inputs
        output_size: user predefined outputs
        possible_probabilities: list of possible probability pairs to choose from

    Returns:

        random MDP

    """

    inputs = [f'i{i+1}' for i in range(input_size)]
    outputs = [f'o{i+1}' for i in range(output_size)]

    if not possible_probabilities:
        possible_probabilities = [(1., ), (1., ), (1., ), (0.9, 0.1),
                                  (0.8, 0.2), (0.7, 0.3), (0.8, 0.1, 0.1),
                                  (0.7, 0.2, 0.1), (0.6, 0.2, 0.1, 0.1)]
        # ensure that there are no infinite loops
        possible_probabilities = [
            p for p in possible_probabilities if len(p) <= num_states
        ]

    state_outputs = outputs.copy()
    states = []
    for i in range(num_states):
        curr_output = state_outputs.pop(0) if state_outputs else random.choice(
            outputs)
        states.append(MdpState(f'q{i}', curr_output))

    state_buffer = list(states)
    for state in states:
        for i in inputs:
            prob = random.choice(possible_probabilities)
            reached_states = []
            for _ in prob:
                while True:
                    new_state = random.choice(
                        state_buffer) if state_buffer else random.choice(
                            states)

                    # ensure determinism
                    if new_state.output not in {
                            s.output
                            for s in reached_states
                    }:
                        break

                    if state_buffer:
                        state_buffer.remove(new_state)

                reached_states.append(new_state)

            for prob, reached_state in zip(prob, reached_states):
                state.transitions[i].append((reached_state, prob))

    return Mdp(states[0], states)