コード例 #1
0
ファイル: BenchmarkSULs.py プロジェクト: DES-Lab/AALpy
def get_faulty_mqtt_SMM():
    from aalpy.automata import StochasticMealyMachine, StochasticMealyState

    s0 = StochasticMealyState('s0')
    s1 = StochasticMealyState('s1')
    s2 = StochasticMealyState('s2')

    s0.transitions['connect'].append((s1, 'CONNACK', 1.))
    s0.transitions['disconnect'].append((s0, 'CONCLOSED', 1.))
    s0.transitions['publish'].append((s0, 'CONCLOSED', 1.))
    s0.transitions['subscribe'].append((s0, 'CONCLOSED', 1.))
    s0.transitions['unsubscribe'].append((s0, 'CONCLOSED', 1.))

    s1.transitions['connect'].append((s0, 'CONCLOSED', 1.))
    s1.transitions['disconnect'].append((s0, 'CONCLOSED', 1.))
    s1.transitions['publish'].append((s1, 'PUBACK', 0.9))
    s1.transitions['publish'].append((s0, 'CONCLOSED', 0.1))
    s1.transitions['subscribe'].append((s2, 'SUBACK', 1.))
    s1.transitions['unsubscribe'].append((s1, 'UNSUBACK', 1.))

    s2.transitions['connect'].append((s0, 'CONCLOSED', 1.))
    s2.transitions['disconnect'].append((s0, 'CONCLOSED', 1.))
    s2.transitions['publish'].append((s2, 'PUBLISH_PUBACK', 1.))
    s2.transitions['subscribe'].append((s2, 'SUBACK', 1.))
    s2.transitions['unsubscribe'].append((s1, 'UNSUBACK', 0.8))
    s2.transitions['unsubscribe'].append((s2, 'SUBACK', 0.2))

    smm = StochasticMealyMachine(s0, [s0, s1, s2])

    return smm
コード例 #2
0
def get_minimal_faulty_coffee_machine_SMM():
    s0 = StochasticMealyState('s0')
    s1 = StochasticMealyState('s1')

    s0.transitions['but'].append((s0, 'init', 1.))
    s0.transitions['coin'].append((s1, 'beep', 1.))
    s1.transitions['but'].append((s0, 'init', 0.1))
    s1.transitions['but'].append((s0, 'coffee', 0.9))
    s1.transitions['coin'].append((s1, 'beep', 1.))

    smm = StochasticMealyMachine(s0, [s0, s1])

    return smm
コード例 #3
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)
コード例 #4
0
ファイル: BenchmarkSULs.py プロジェクト: DES-Lab/AALpy
def get_small_gridworld():
    from aalpy.automata import StochasticMealyMachine, StochasticMealyState

    s0 = StochasticMealyState('s0')
    s1 = StochasticMealyState('s1')
    s2 = StochasticMealyState('s2')
    s3 = StochasticMealyState('s3')

    p_g = 0.8
    p_m = 0.6

    # gridworld of the form
    # W W W W with a start in the top left
    # W G M W states like s0 s1
    # W M G W             s2 s3
    # W W W W

    s0.transitions['north'].append((s0, 'wall', 1.))
    s0.transitions['west'].append((s0, 'wall', 1.))
    s0.transitions['east'].append((s1, 'mud', p_m))
    s0.transitions['east'].append((s3, 'grass', 1 - p_m))
    s0.transitions['south'].append((s2, 'mud', p_m))
    s0.transitions['south'].append((s3, 'grass', 1 - p_m))

    s1.transitions['north'].append((s1, 'wall', 1.))
    s1.transitions['east'].append((s1, 'wall', 1.))
    s1.transitions['west'].append((s0, 'grass', p_g))
    s1.transitions['west'].append((s2, 'mud', 1 - p_g))
    s1.transitions['south'].append((s3, 'grass', p_g))
    s1.transitions['south'].append((s2, 'mud', 1 - p_g))

    s2.transitions['south'].append((s2, 'wall', 1.))
    s2.transitions['west'].append((s2, 'wall', 1.))
    s2.transitions['east'].append((s3, 'grass', p_g))
    s2.transitions['east'].append((s1, 'mud', 1 - p_g))
    s2.transitions['north'].append((s0, 'grass', p_g))
    s2.transitions['south'].append((s1, 'mud', 1 - p_g))

    s3.transitions['south'].append((s3, 'wall', 1.))
    s3.transitions['east'].append((s3, 'wall', 1.))
    s3.transitions['west'].append((s2, 'mud', p_m))
    s3.transitions['west'].append((s0, 'grass', 1 - p_m))
    s3.transitions['north'].append((s1, 'mud', p_m))
    s3.transitions['north'].append((s0, 'grass', 1 - p_m))

    smm = StochasticMealyMachine(s0, [s0, s1, s2, s3])

    return smm
コード例 #5
0
def to_smm():
    # 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 model.states:
        mdp_state = StochasticMealyState(state.state_id)
        moore_mdp_state_map[state.prefix] = mdp_state
        if not state.prefix:
            initial_mdp_state = mdp_state

    assert initial_mdp_state

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

        for i in alphabet:
            reached_state = state.transitions[i].prefix
            correct_output = state.output_fun[i]
            # if i in {'pairing_req', 'mtu_req'} and mdp_state.output != moore_mdp_state_map[reached_moore].output:
            if state_num % 6 == 0:
                last_out = model.compute_output_seq(
                    model.initial_state,
                    state.prefix[:-1]) if state.prefix else "NO_RESPONSE"
                if not last_out or last_out == correct_output:
                    last_out = 'NO_RESPONSE'
                mdp_state.transitions[i].append((mdp_state, last_out[-1], 0.2))
                mdp_state.transitions[i].append(
                    (moore_mdp_state_map[reached_state], correct_output, 0.8))
            if state_num % 5 == 0 and i in {
                    'length_req', 'length_rsp', 'feature_rsp'
            } and len(state.prefix) == 2:
                mdp_state.transitions[i].append(
                    (moore_mdp_state_map[model.initial_state.prefix],
                     'SYSTEM_CRASH', 0.1))
                mdp_state.transitions[i].append(
                    (moore_mdp_state_map[reached_state], correct_output, 0.9))
            else:
                mdp_state.transitions[i].append(
                    (moore_mdp_state_map[reached_state], correct_output, 1.))

    mdp = StochasticMealyMachine(initial_mdp_state,
                                 list(moore_mdp_state_map.values()))
    return mdp
コード例 #6
0
ファイル: BenchmarkSULs.py プロジェクト: DES-Lab/AALpy
def get_faulty_coffee_machine_SMM():
    from aalpy.automata import StochasticMealyMachine, StochasticMealyState

    s0 = StochasticMealyState('s0')
    s1 = StochasticMealyState('s1')
    s2 = StochasticMealyState('s2')

    s0.transitions['but'].append((s0, 'init', 1.))
    s0.transitions['coin'].append((s1, 'beep', 1.))
    s1.transitions['but'].append((s0, 'init', 0.1))
    s1.transitions['but'].append((s2, 'coffee', 0.9))
    s1.transitions['coin'].append((s1, 'beep', 1.))
    s2.transitions['but'].append((s0, 'init', 1.))
    s2.transitions['coin'].append((s1, 'beep', 1.))

    smm = StochasticMealyMachine(s0, [s0, s1, s2])

    return smm
コード例 #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()))
コード例 #8
0
ファイル: AutomatonGenerators.py プロジェクト: DES-Lab/AALpy
def generate_random_smm(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: number of outputs
        possible_probabilities: list of possible probability pairs to choose from

    Returns:

        random SMM

    """

    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
        ]

    states = []
    for i in range(num_states):
        states.append(StochasticMealyState(f'q{i}'))

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

                    # ensure determinism
                    if o not in transition_outputs:
                        break

                    if output_buffer:
                        output_buffer.remove(o)
                    if state_buffer:
                        state_buffer.remove(new_state)

                reached_states.append(new_state)
                transition_outputs.append(o)

            for index in range(len(prob)):
                state.transitions[i].append(
                    (reached_states[index], transition_outputs[index],
                     prob[index]))

    return StochasticMealyMachine(states[0], states)
コード例 #9
0
def load_automaton_from_file(path, automaton_type, compute_prefixes=False):
    """
    Loads the automaton from the file.
    Standard of the automatas strictly follows syntax found at: https://automata.cs.ru.nl/Syntax/Overview.

    Args:

        path: path to the file

        automaton_type: type of the automaton, if not specified it will be automatically determined according,
            one of ['dfa', 'mealy', 'moore', 'mdp', 'smm', 'onfsm']

        compute_prefixes: it True, shortest path to reach every state will be computed and saved in the prefix of
            the state. Useful when loading the model to use them as a equivalence oracle. (Default value = False)

    Returns:
      automaton

    """
    graph = graph_from_dot_file(path)[0]

    assert automaton_type in automaton_types

    node = MealyState if automaton_type == 'mealy' else DfaState if automaton_type == 'dfa' else MooreState
    node = MdpState if automaton_type == 'mdp' else StochasticMealyState if automaton_type == 'smm' else node
    node = OnfsmState if automaton_type == 'onfsm' else node
    assert node is not None

    node_label_dict = dict()
    for n in graph.get_node_list():
        if n.get_name() == '__start0' or n.get_name() == '':
            continue
        label = None
        if 'label' in n.get_attributes().keys():
            label = n.get_attributes()['label']
            label = _process_label(label)

        node_name = n.get_name()
        output = None
        if automaton_type == 'moore' and label != "":
            label_output = _process_label(label)
            label = label_output.split('|')[0]
            output = label_output.split('|')[1]

        if automaton_type == 'mdp':
            node_label_dict[node_name] = node(node_name, label)
        else:
            node_label_dict[node_name] = node(
                label, output) if automaton_type == 'moore' else node(label)

        if 'shape' in n.get_attributes().keys(
        ) and 'doublecircle' in n.get_attributes()['shape']:
            node_label_dict[node_name].is_accepting = True

    initial_node = None
    for edge in graph.get_edge_list():
        if edge.get_source() == '__start0':
            initial_node = node_label_dict[edge.get_destination()]
            continue
        source = node_label_dict[edge.get_source()]
        destination = node_label_dict[edge.get_destination()]
        label = edge.get_attributes()['label']
        label = _process_label(label)
        if automaton_type == 'mealy':
            inp = label.split('/')[0]
            out = label.split('/')[1]
            inp = int(inp) if inp.isdigit() else inp
            out = int(out) if out.isdigit() else out
            source.transitions[inp] = destination
            source.output_fun[inp] = out
        elif automaton_type == 'onfsm':
            inp = label.split('/')[0]
            out = label.split('/')[1]
            inp = int(inp) if inp.isdigit() else inp
            out = int(out) if out.isdigit() else out
            source.transitions[inp].append((out, destination))
        elif automaton_type == 'smm':
            inp = label.split('/')[0]
            out_prob = label.split('/')[1]
            out = out_prob.split(':')[0]
            prob = out_prob.split(':')[1]
            inp = int(inp) if inp.isdigit() else inp
            out = int(out) if out.isdigit() else out
            source.transitions[inp].append((destination, out, float(prob)))
        elif automaton_type == 'mdp':
            inp = label.split(':')[0]
            prob = label.split(':')[1]
            inp = int(inp) if inp.isdigit() else inp
            prob = float(prob)
            source.transitions[inp].append((destination, prob))
        else:
            source.transitions[int(label) if label.isdigit(
            ) else label] = destination

    if automaton_type == 'dfa':
        automaton = Dfa(initial_node, list(node_label_dict.values()))
    elif automaton_type == 'moore':
        automaton = MooreMachine(initial_node, list(node_label_dict.values()))
    elif automaton_type == 'mdp':
        automaton = Mdp(initial_node, list(node_label_dict.values()))
    elif automaton_type == 'smm':
        automaton = StochasticMealyMachine(initial_node,
                                           list(node_label_dict.values()))
    elif automaton_type == 'onfsm':
        automaton = Onfsm(initial_node, list(node_label_dict.values()))
    else:
        automaton = MealyMachine(initial_node, list(node_label_dict.values()))
    assert automaton.is_input_complete()
    if compute_prefixes:
        for state in automaton.states:
            state.prefix = automaton.get_shortest_path(automaton.initial_state,
                                                       state)
    return automaton