Пример #1
0
def _fixEventEdge(edge, system, only_print=False):
    """
    fix a bad edge caused by external event
    :param edge: the bad edge
    :param system: the IoTSystem
    :return: [[patches], [patches], ...], each 'patches' represents a possible fix
    """
    ts = system.transition_system

    # First: find all possible actions
    action_list = list()
    for action, dst_field in system.getAction(edge.dst_field, False):
        # after the external event, what action can be triggered?
        dst_label = system.getLabel(dst_field)
        ap_dict = dict()
        for ap, value in zip(ts.ap_list, dst_label):
            ap_dict[ap] = value
        if not calculateBoolean(edge.ltl_req, ap_dict):
            # is good for redirecting, doesn't violate ltl by entering accepting cluster
            action_list.append(action)

    # Second: get the correct trigger action
    trigger = edge.action

    # Third: find minimum condition that only cover the source state of the edge using hitting set
    src_label = ts.label_list[edge.src_index_ts]
    src_ap_list = [(ap if src_label[index] else '!' + ap)
                   for index, ap in enumerate(ts.ap_list) if '.' in ap]

    hitting_set_list = list()
    for trans in ts.trans_list:
        if trans.act == edge.action and ts.state_list[
                trans.src_index].field != edge.src_field:
            label = system.getLabel(ts.state_list[trans.src_index].field)
            conflict_ap_list = [
                '!' + ap if label[index] else ap
                for index, ap in enumerate(ts.ap_list) if '.' in ap
            ]
            hitting_set_list.append(conflict_ap_list)

    condition = hittingSet(src_ap_list, hitting_set_list)

    if only_print:
        print('trigger: %s, condition: %s' % (trigger, str(condition)))
    else:
        # return all possible patches
        result = list()
        for action in action_list:
            new_tap = Tap(action, trigger, condition)
            result.append([Patch('add', '', new_tap)])

        return result
Пример #2
0
def _fixConditionGenerator(system, ltl, record_exp_list, include_orig=False):
    """
    generate a set of bad edge conditions (trigger, condition, possible_actions_list)
    another return value is a set of all other edge conditions in safety or boundary [(trigger, condition)] ..
    :param system:
    :param ltl:
    :return:
    """
    bad_edges, other_edges = _getBadEdges(system, ltl, record_exp_list)
    buchi_ltl = Buchi.ltlToBuchi(ltl)

    result = list()
    others = list()
    for bad_edge in bad_edges:
        ap_list = [ap for ap in system.getApList(bad_edge.src_field) if '@' not in ap and 'trigger' not in ap]
        ap_list = ap_list + ['!' + ap for ap in system.getAllAp()
                             if '@' not in ap and 'trigger' not in ap and
                             ap not in ap_list and ap not in system.tap_dict]
        condition = ' & '.join(ap_list)
        trigger = bad_edge.action
        action_list = list()
        for action, dst_field in system.getAction(src_field=bad_edge.dst_field, ext=False):
            label = system.getLabel(dst_field)
            ap_dict = dict()
            for value, ap in zip(label, system.transition_system.ap_list):
                ap_dict[ap] = value
            ap_dict = {**ap_dict, **{key: _recordSatisfy(action, key) for key in record_exp_list}}
            if not calculateBoolean(_getLTLReq(buchi_ltl, bad_edge.src_index_ltl, bad_edge.dst_index_ltl), ap_dict):
                action_list.append(action)

        result.append((trigger, condition, action_list))

    if include_orig:
        for k, tap in system.tap_dict.items():
            condition = ' & '.join(tap.condition)
            trigger = tap.trigger
            action_list = [tap.action]
            result.append((trigger, condition, action_list))
        for edge in other_edges:
            # should add every edge that doesn't trigger any rule
            if not system.isTriggeredState(edge.dst_field):
                ap_list = [ap for ap in system.getApList(edge.src_field) if '@' not in ap and 'trigger' not in ap]
                ap_list = ap_list + ['!' + ap for ap in system.getAllAp()
                                     if '@' not in ap and 'trigger' not in ap and
                                     ap not in ap_list and ap not in system.tap_dict]
                condition = ' & '.join(ap_list)
                trigger = edge.action

                others.append((trigger, condition))
    else:
        for edge in other_edges:
            ap_list = [ap for ap in system.getApList(edge.src_field) if '@' not in ap and 'trigger' not in ap]
            ap_list = ap_list + ['!' + ap for ap in system.getAllAp()
                                 if '@' not in ap and 'trigger' not in ap and
                                 ap not in ap_list and ap not in system.tap_dict]
            condition = ' & '.join(ap_list)
            trigger = edge.action

            others.append((trigger, condition))

    return result, others
Пример #3
0
def drawPatchList(system, ltl, patch_list, file_name):
    """
    given system and ltl property, draw graph representation of certain patches as png
    :param system: the smart home system
    :param ltl: ltl formula
    :param patch_list: the patch_list (FixPatch)
    :param file_name: file to be written
    :return:
    """
    ts = system.transition_system
    buchi_ts = Buchi.tsToGenBuchi(ts)
    buchi_ltl = Buchi.ltlToBuchi(ltl)
    (buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)
    group = [s2 for s1, s2 in pairs]

    modified_buchi = ModifiedBuchi(buchi_final)

    field_list = [state.field for state in ts.state_list]

    for edge_index, edge in enumerate(buchi_final.edge_list):
        src_index_ts = pairs[edge.src][0]
        dst_index_ts = pairs[edge.dst][0]
        src_index_ltl = pairs[edge.src][1]
        dst_index_ltl = pairs[edge.dst][1]
        src_field = field_list[src_index_ts]
        dst_field = field_list[dst_index_ts]
        action = _getAction(ts, src_field, dst_field)

        if '>' in action:
            # this is an action triggered by some old rule
            # should see if it's not triggered in new rule
            rule_dict = dict([(tap_name, translateTapToRule(tap))
                              for tap_name, tap in system.tap_dict.items()])
            old_rule_name = re.match(r'rule\((?P<rule_name>\w+)\)->[^ ]+',
                                     action).group('rule_name')
            old_rule = rule_dict[old_rule_name]
            for patch in patch_list:
                if patch.type == 'delete' and patch.rule_name == old_rule_name:
                    # then this edge is deleted
                    modified_buchi.markDeletedEdge(edge_index)
                    break
                if patch.type == 'change' and patch.rule_name == old_rule_name:
                    # then this rule is changed, need to see whether edge still triggered
                    new_rule = patch.rule
                    if isinstance(new_rule, ESERule):
                        orig_field = system.getLastStateField(
                            new_rule.trigger, src_field)
                        if orig_field:
                            if not system.apSatisfied(new_rule.condition,
                                                      orig_field):
                                # then this rule is not triggered anymore
                                modified_buchi.markDeletedEdge(edge_index)
                                break
        elif '.' in action:
            # this is an external event
            # should see if some new rules trigger this
            for patch in patch_list:
                new_rule = patch.rule
                add_edge_flag = 0
                if patch.type in ('add', 'change') and not system.isTriggeredState(dst_field) and\
                        new_rule.trigger == action:
                    if isinstance(new_rule, EERule):
                        # should add an new edge
                        add_edge_flag = 1
                    elif isinstance(new_rule, ESERule) and \
                            system.apSatisfied(new_rule.condition, src_field):
                        # should add an new edge
                        add_edge_flag = 1

                if add_edge_flag:
                    # this is an new edge, redirection
                    new_field = system.applyActionWithoutTriggering(
                        new_rule.action, dst_field)

                    new_index_ts = ts.getIndex(
                        new_field)  # which node it goes in ts

                    ap_list = ts.ap_list
                    new_label = system.getLabel(new_field)

                    var_dict = dict()
                    for ap, label in zip(ap_list, new_label):
                        var_dict[ap] = label
                    # use var_dict to calculate which edge it goes in ltl buchi automata
                    new_index_ltl = -1  # which node it goes in ltl
                    for e in buchi_ltl.edge_list:
                        if e.src == src_index_ltl:
                            if calculateBoolean(e.ap, var_dict):
                                new_index_ltl = e.dst

                    src_final_index = pairs.index(
                        (src_index_ts, src_index_ltl))
                    new_final_index = pairs.index(
                        (new_index_ts, new_index_ltl))

                    modified_buchi.markDeletedEdge(edge_index)
                    modified_buchi.addNewEdge(src_final_index, new_final_index)
                    break

    modified_buchi.writeToGv(file_name, group)
Пример #4
0
def drawPatch(system, ltl, patch, file_name):
    """
    given system and ltl property, draw graph representation of certain patch as png
    :param system: the smart home system
    :param ltl: ltl formula
    :param patch: the patch (FixPatch)
    :param file_name: file to be written
    :return:
    """
    ts = system.transition_system
    buchi_ts = Buchi.tsToGenBuchi(ts)
    buchi_ltl = Buchi.ltlToBuchi(ltl)
    (buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)
    group = [s2 for s1, s2 in pairs]

    modified_buchi = ModifiedBuchi(buchi_final)

    rule_dict = dict([(tap_name, translateTapToRule(tap))
                      for tap_name, tap in system.tap_dict.items()])
    new_rule = None if patch.type == 'delete' else patch.rule
    old_rule = None if patch.type == 'add' else rule_dict[patch.rule_name]

    field_list = [state.field for state in ts.state_list]

    for edge_index, edge in enumerate(buchi_final.edge_list):
        src_index_ts = pairs[edge.src][0]
        dst_index_ts = pairs[edge.dst][0]
        src_index_ltl = pairs[edge.src][1]
        dst_index_ltl = pairs[edge.dst][1]
        src_field = field_list[src_index_ts]
        dst_field = field_list[dst_index_ts]
        action = _getAction(ts, src_field, dst_field)

        if '>' in action:
            # this is an action triggered by a rule
            # is it handled by old rule?
            flag_old, flag_new = False, False
            if old_rule:
                old_rule_name = patch.rule_name
                if old_rule_name in action:
                    # handled
                    flag_old = True
            # is it handled by new rule?
            if new_rule:
                if isinstance(new_rule, ESERule):
                    # TODO: should check if this is the correct! should it be last state?
                    if system.apSatisfied(new_rule.condition, src_field):
                        # handled
                        flag_new = True
                elif isinstance(new_rule, EERule):
                    # handled
                    flag_new = True

            if flag_old and not flag_new:
                # this edge is deleted
                modified_buchi.markDeletedEdge(edge_index)

        else:
            # this is an external event
            if '.' in action:
                # it is not handled by old rule
                # is it handled by new rule? old rule?
                if new_rule:
                    flag_new, flag_old = False, False
                    if new_rule.trigger == action:
                        if isinstance(new_rule, EERule):
                            flag_new = True
                        elif isinstance(new_rule, ESERule):
                            if system.apSatisfied(new_rule.condition,
                                                  src_field):
                                flag_new = True
                    if old_rule:
                        if old_rule.trigger == action:
                            if isinstance(old_rule, EERule):
                                flag_old = True
                            elif isinstance(old_rule, ESERule):
                                if system.apSatisfied(old_rule.condition,
                                                      src_field):
                                    flag_old = True

                    if flag_new and not flag_old:
                        # this is a new triggered edge, redirection
                        new_field = system.applyActionWithoutTriggering(
                            new_rule.action, dst_field)

                        new_index_ts = ts.getIndex(
                            new_field)  # which node it goes in ts

                        ap_list = ts.ap_list
                        new_label = system.getLabel(new_field)

                        var_dict = dict()
                        for ap, label in zip(ap_list, new_label):
                            var_dict[ap] = label
                        # use var_dict to calculate which edge it goes in ltl buchi automata
                        new_index_ltl = -1  # which node it goes in ltl
                        for e in buchi_ltl.edge_list:
                            if e.src == src_index_ltl:
                                if calculateBoolean(e.ap, var_dict):
                                    new_index_ltl = e.dst

                        src_final_index = pairs.index(
                            (src_index_ts, src_index_ltl))
                        new_final_index = pairs.index(
                            (new_index_ts, new_index_ltl))

                        modified_buchi.markDeletedEdge(edge_index)
                        modified_buchi.addNewEdge(src_final_index,
                                                  new_final_index)

    modified_buchi.writeToGv(file_name, group)