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
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
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
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
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
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()))
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)