def calculateBoolean(formula, var_dict): """ given boolean variable value, calculate the value of a boolean formula (!, &, |, brackets are supported) :param formula: the formula :param var_dict: var_name->value dictionary :return: """ token_list = parse(formula, ops, re_splitter) stack = list() for token in token_list: if token == '!': stack[-1] = not stack[-1] elif token == '&': stack[-2] = stack[-1] and stack[-2] stack.pop() elif token == '|': stack[-2] = stack[-1] or stack[-2] stack.pop() elif token in var_dict: stack.append(var_dict[token]) elif token == '0': stack.append(False) elif token == '1': stack.append(True) else: raise Exception('Unknown AP token %s in edge formula' % token) if len(stack) != 1: raise Exception('Wrong edge AP formula format!') return stack[0]
def toSpot(self, bdict=default_bdd_dict): """ Translate a (generalized) buchi automaton into bdd in spot package :param bdict: the bdd_dict that the output automaton uses :return: an spot generalized buchi automaton """ aut = spot.make_twa_graph(bdict) ap_list = dict() state_map = dict() for ap in self.ap_list: # if ap not in ['0', '1']: ap_list[ap] = buddy.bdd_ithvar(aut.register_ap(ap)) aut.set_generalized_buchi(self.acc_num) aut.prop_state_acc(1) new_index = 0 for index, state in self.state_dict.items(): aut.new_state() state_map[index] = new_index new_index = new_index + 1 aut.set_init_state(state_map[self.getInitState()]) for edge in self.edge_list: acc = self.getStateAcc(edge.src) ap_calc_list = parse(edge.ap, ops, re_splitter) ap_stack = list() for token in ap_calc_list: if token == '!': ap_stack[-1] = -ap_stack[-1] elif token == '&': ap_stack[-2] = ap_stack[-1] & ap_stack[-2] ap_stack.pop() elif token == '|': ap_stack[-2] = ap_stack[-1] | ap_stack[-2] ap_stack.pop() elif token in self.ap_list: ap_stack.append(ap_list[token]) elif token == '0': ap_stack.append(buddy.bddfalse) elif token == '1': ap_stack.append(buddy.bddtrue) else: raise Exception('Unknown AP token %s in edge formula' % token) if len(ap_stack) != 1: raise Exception('Wrong edge AP formula format!') aut.new_edge(state_map[edge.src], state_map[edge.dst], ap_stack[0], acc) return aut, state_map
def _getValueDict(formula): value_dict = dict() re_splitter = r'(\s+|\(|\)|\&|\||!|<|>|=|F|G|U|W|\#|\*|X|@)' ops = { '!': Operator('!', 1, 4, 1), '&': Operator('&', 2, 2, 0), '|': Operator('|', 2, 2, 0), '<': Operator('<', 2, 6, 0), '>': Operator('>', 2, 6, 0), '=': Operator('=', 2, 6, 0), 'G': Operator('G', 1, 3, 1), 'F': Operator('F', 1, 3, 1), 'U': Operator('U', 2, 3, 0), 'X': Operator('X', 1, 3, 1), 'W': Operator('W', 2, 3, 0), '#': Operator('#', 2, 5, 0), '*': Operator('*', 2, 5, 0), '@': Operator('@', 1, 5, 1) } post_exp = parse(formula, ops, re_splitter) stack = list() for token in post_exp: if token not in ops: stack.append(token) else: if ops[token].n_args == 1: stack[-1] = token + str(stack[-1]) elif ops[token].n_args == 2: if token in ('<', '>', '='): if stack[-2] not in value_dict: value_dict[stack[-2]] = [stack[-1]] elif stack[-1] not in value_dict[stack[-2]]: value_dict[stack[-2]].append(stack[-1]) stack[-2] = stack[-2] + token + stack[-1] stack.pop() return value_dict
def _getTimeExpList(formula): time_exp_list = list() recorded_list = list() re_splitter = r'(\s+|\(|\)|\&|\||!|<|>|=|F|G|U|W|\#|\*|X|@)' ops = { '!': Operator('!', 1, 4, 1), '&': Operator('&', 2, 2, 0), '|': Operator('|', 2, 2, 0), '<': Operator('<', 2, 6, 0), '>': Operator('>', 2, 6, 0), '=': Operator('=', 2, 6, 0), 'G': Operator('G', 1, 3, 1), 'F': Operator('F', 1, 3, 1), 'U': Operator('U', 2, 3, 0), 'X': Operator('X', 1, 3, 1), 'W': Operator('W', 2, 3, 0), '#': Operator('#', 2, 5, 0), '*': Operator('*', 2, 5, 0), '@': Operator('@', 1, 5, 1) } post_exp = parse(formula, ops, re_splitter) stack = list() for token in post_exp: if token not in ops: stack.append(token) else: if ops[token].n_args == 1: stack[-1] = token + str(stack[-1]) if token == '@': recorded_list.append(stack[-1]) elif ops[token].n_args == 2: stack[-2] = stack[-2] + token + stack[-1] if token in ('#', '*'): time_exp_list.append(stack[-2]) stack.pop() return list(set(time_exp_list)), list(set(recorded_list))
def ltlFormat(ltl): def isfloat(s): try: float(s) return True except ValueError: return False re_splitter = r'(\s+|\(|\)|\&|\||!|<|>|=|F|G|U|W|\#|\*|X|@)' ops = { '!': Operator('!', 1, 4, 1), '&': Operator('&', 2, 2, 0), '|': Operator('|', 2, 2, 0), '<': Operator('<', 2, 6, 0), '>': Operator('>', 2, 6, 0), '=': Operator('=', 2, 6, 0), 'G': Operator('G', 1, 3, 1), 'F': Operator('F', 1, 3, 1), 'U': Operator('U', 2, 3, 0), 'X': Operator('X', 1, 3, 1), 'W': Operator('W', 2, 3, 0), '#': Operator('#', 2, 5, 0), '*': Operator('*', 2, 5, 0), '@': Operator('@', 1, 5, 1) } time_record_exp_dict = dict() time_record_prefix = '________________' ltl_post_exp = parse(ltl, ops, re_splitter) stack = list() for token in ltl_post_exp: if token not in ops: stack.append(token) else: if token in ('#', '*'): time_record_exp_dict[time_record_prefix + str( len(time_record_exp_dict))] = stack[-2] + token + stack[-1] stack[-2] = time_record_prefix + str( len(time_record_exp_dict) - 1) stack.pop() elif token == '@': time_record_exp_dict[ time_record_prefix + str(len(time_record_exp_dict))] = token + stack[-1] stack[-1] = time_record_prefix + str( len(time_record_exp_dict) - 1) else: if ops[token].n_args == 2: if token in ('<', '=', '>'): stack[-2] = stack[-2] + token + stack[-1] else: stack[-2] = '(' + stack[-2] + token + stack[-1] + ')' stack.pop() elif ops[token].n_args == 1: stack[-1] = token + '(' + stack[-1] + ')' ltl_post_exp = parse(stack[0], ops, re_splitter) stack = list() for token in ltl_post_exp: if token not in ops: stack.append(token) else: if ops[token].n_args == 2: if token == '<': stack[-2] = stack[-2] + 'LessThan' + stack[-1].replace( '.', '_') elif token == '>': stack[-2] = stack[-2] + 'GreaterThan' + stack[-1].replace( '.', '_') elif token == '=': if stack[-1] == 'true': stack[-2] = stack[-2] + 'IsTrue' elif stack[-1] == 'false': stack[-2] = '!' + stack[-2] + 'IsTrue' elif not isfloat(stack[-1]): # should be set stack[-2] = stack[-2] + 'Is' + stack[-1].capitalize() else: exp1 = '!' + stack[-2] + 'LessThan' + stack[ -1].replace('.', '_') exp2 = '!' + stack[-2] + 'GreaterThan' + stack[ -1].replace('.', '_') stack[-2] = '(' + exp1 + ' & ' + exp2 + ')' else: stack[-2] = '(' + stack[-2] + ' ' + token + ' ' + stack[ -1] + ')' stack.pop() elif ops[token].n_args == 1: stack[-1] = token + '(' + stack[-1] + ')' for key, time_exp in time_record_exp_dict.items(): stack[0] = stack[0].replace(key, '"%s"' % time_exp) return stack[0]
def namedTapFormat(tap_dict, critical_value_dict): def isfloat(s): try: float(s) return True except ValueError: return False new_tap_dict = dict() re_splitter = r'(\s+|\(|\)|\&|\||!|<|>|=|F|G|U|W|\#|\*|X|@)' ops = { '!': Operator('!', 1, 4, 1), '&': Operator('&', 2, 2, 0), '|': Operator('|', 2, 2, 0), '<': Operator('<', 2, 6, 0), '>': Operator('>', 2, 6, 0), '=': Operator('=', 2, 6, 0), 'G': Operator('G', 1, 3, 1), 'F': Operator('F', 1, 3, 1), 'U': Operator('U', 2, 3, 0), 'X': Operator('X', 1, 3, 1), 'W': Operator('W', 2, 3, 0), '#': Operator('#', 2, 5, 0), '*': Operator('*', 2, 5, 0), '@': Operator('@', 1, 5, 1) } for tap_name, tap in tap_dict.items(): new_trigger = list() if not re.match(r'^tick\[(?P<time_exp>[()\w<>=#*.]+)\]$', tap.trigger): trigger_post_exp = parse(tap.trigger, ops, re_splitter) if trigger_post_exp[-1] == '<': value = int(trigger_post_exp[-2]) crit_list = critical_value_dict[trigger_post_exp[-3]] left_list = crit_list[:-1] right_list = crit_list[1:] mid_list = [(v1 + v2) / 2 for v1, v2 in zip(left_list, right_list)] enhanced_list = crit_list + mid_list + [ min(crit_list) - 1, max(crit_list) + 1 ] sat_list = [v for v in enhanced_list if v < value] for sat_val in sat_list: new_trigger.append(trigger_post_exp[-3] + 'SetTo' + str(sat_val).replace('.', '_')) elif trigger_post_exp[-1] == '>': value = int(trigger_post_exp[-2]) crit_list = critical_value_dict[trigger_post_exp[-3]] left_list = crit_list[:-1] right_list = crit_list[1:] mid_list = [(v1 + v2) / 2 for v1, v2 in zip(left_list, right_list)] enhanced_list = crit_list + mid_list + [ min(crit_list) - 1, max(crit_list) + 1 ] sat_list = [v for v in enhanced_list if v > value] for sat_val in sat_list: new_trigger.append(trigger_post_exp[-3] + 'SetTo' + str(sat_val).replace('.', '_')) elif trigger_post_exp[-1] == '=': if not isfloat(trigger_post_exp[-2]): new_trigger.append(trigger_post_exp[-3] + 'Set' + trigger_post_exp[-2].capitalize()) else: new_trigger.append(trigger_post_exp[-3] + 'SetTo' + trigger_post_exp[-2].replace('.', '_')) else: new_trigger.append(tap.trigger) condition = list() for cond in tap.condition: if '#' in cond or '*' in cond: condition.append(cond) else: cond_post_exp = parse(cond, ops, re_splitter) if cond_post_exp[-1] == '=': if cond_post_exp[-2] == 'true': condition.append(cond_post_exp[-3] + 'IsTrue') elif cond_post_exp[-2] == 'false': condition.append('!' + cond_post_exp[-3] + 'IsTrue') elif isfloat(cond_post_exp[-2]): condition.append('!' + cond_post_exp[-3] + 'GreaterThan' + cond_post_exp[-2].replace('.', '_')) condition.append('!' + cond_post_exp[-3] + 'LessThan' + cond_post_exp[-2].replace('.', '_')) else: # should be 'set' condition.append(cond_post_exp[-3] + 'Is' + cond_post_exp[2].capitalize()) elif cond_post_exp[-1] == '<': condition.append(cond_post_exp[-3] + 'LessThan' + cond_post_exp[-2].replace('.', '_')) elif cond_post_exp[-1] == '>': condition.append(cond_post_exp[-3] + 'GreaterThan' + cond_post_exp[-2].replace('.', '_')) act_post_exp = parse(tap.action, ops, re_splitter) if not isfloat(act_post_exp[-2]): action = act_post_exp[-3] + 'Set' + act_post_exp[-2].capitalize() else: action = act_post_exp[-3] + 'SetTo' + act_post_exp[-2].replace( '.', '_') for trigger, new_tap_index in zip(new_trigger, range(len(new_trigger))): new_tap_dict['%s.%d' % (tap_name, new_tap_index)] = Tap( action, trigger, condition) return new_tap_dict
def getChannelList(ltl, tap_list): channel_list = list() re_splitter = r'(\s+|\(|\)|\&|\||!|<|>|=|F|G|U|W|\#|\*|X|@)' ops = { '!': Operator('!', 1, 4, 1), '&': Operator('&', 2, 2, 0), '|': Operator('|', 2, 2, 0), '<': Operator('<', 2, 6, 0), '>': Operator('>', 2, 6, 0), '=': Operator('=', 2, 6, 0), 'G': Operator('G', 1, 3, 1), 'F': Operator('F', 1, 3, 1), 'U': Operator('U', 2, 3, 0), 'X': Operator('X', 1, 3, 1), 'W': Operator('W', 2, 3, 0), '#': Operator('#', 2, 5, 0), '*': Operator('*', 2, 5, 0), '@': Operator('@', 1, 5, 1) } ltl_post_exp = parse(ltl, ops, re_splitter) cap_list = [ token for token in ltl_post_exp if token not in ops and '.' in token and not token[0].isnumeric() ] channel_list = list( set(channel_list + [cap.split('.')[0] for cap in cap_list])) tap_channel_list = list() tap_cap_list = list() for tap in tap_list: time_match = re.match(r'^tick\[(?P<time_exp>[()\w<>=#*]+)\]$', tap.trigger) if time_match: trigger = time_match.group('time_exp') else: trigger = tap.trigger trigger_post_exp = parse(trigger, ops, re_splitter) trigger_channel_l = list({ token.split('.')[0] for token in trigger_post_exp if token not in ops and '.' in token and not token[0].isnumeric() }) trigger_cap_l = list({ token for token in trigger_post_exp if token not in ops and '.' in token and not token[0].isnumeric() }) action_post_exp = parse(tap.action, ops, re_splitter) action_channel_l = list({ token.split('.')[0] for token in action_post_exp if token not in ops and '.' in token and not token[0].isnumeric() }) action_cap_l = list({ token for token in action_post_exp if token not in ops and '.' in token and not token[0].isnumeric() }) for cond in tap.condition: cond_post_exp = parse(cond, ops, re_splitter) cond_channel_l = list({ token.split('.')[0] for token in cond_post_exp if token not in ops and '.' in token and not token[0].isnumeric() }) cond_cap_l = list({ token for token in cond_post_exp if token not in ops and '.' in token and not token[0].isnumeric() }) trigger_channel_l = list(set(trigger_channel_l + cond_channel_l)) trigger_cap_l = list(set(trigger_cap_l + cond_cap_l)) tap_channel_list.append( (trigger_channel_l, action_channel_l, tap_list.index(tap))) tap_cap_list.append((trigger_cap_l, action_cap_l, tap_list.index(tap))) # TODO: should be careful about this change, seems dangerous to me # channel_to_search = copy.deepcopy(channel_list) # new_tap_list = list() # while channel_to_search: # ch = channel_to_search.pop() # for trigger_channel_l, action_channel_l, tap_index in tap_channel_list: # if ch in action_channel_l: # new_tap_list.append(tap_index) # for ch_t in trigger_channel_l: # if ch_t not in channel_list: # channel_list.append(ch_t) # channel_to_search.append(ch_t) cap_to_search = copy.deepcopy(cap_list) new_tap_list = list() while cap_to_search: cap = cap_to_search.pop() for trigger_cap_l, action_cap_l, tap_index in tap_cap_list: if cap in action_cap_l: new_tap_list.append(tap_index) for cap_t in trigger_cap_l: if cap_t not in cap_list: cap_list.append(cap_t) cap_to_search.append(cap_t) new_tap_list = list(set(new_tap_list)) new_tap_list = [tap_list[index] for index in new_tap_list] channel_list = [cap_name.split('.')[0] for cap_name in cap_list] return list(set(channel_list)), list(set(cap_list)), new_tap_list