Exemple #1
0
def generateGraph(system, ltl, folder, only_action=False):
    ts = system.transition_system
    buchi_ts = Buchi.tsToGenBuchi(ts)
    buchi_ltl = Buchi.ltlToBuchi(ltl)
    (buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)

    filename_ts = folder + 'ts.gv' if folder.endswith(
        '/') else folder + '/ts.gv'
    filename_ltl = folder + 'ltl.gv' if folder.endswith(
        '/') else folder + '/ltl.gv'
    filename_final = folder + 'final.gv' if folder.endswith(
        '/') else folder + '/final.gv'

    png_ts = folder + 'ts.png' if folder.endswith('/') else folder + '/ts.png'
    png_ltl = folder + 'ltl.png' if folder.endswith(
        '/') else folder + '/ltl.png'
    png_final = folder + 'final.png' if folder.endswith(
        '/') else folder + '/final.png'

    group = [s2 for s1, s2 in pairs]

    try:
        os.stat(folder)
    except:
        os.mkdir(folder)

    buchi_ts.writeToGv(filename_ts, only_action=only_action)
    buchi_ltl.writeToGv(filename_ltl)
    buchi_final.writeToGv(filename_final, group, only_action=only_action)

    os.system('dot -Tpng -o %s %s' % (png_ts, filename_ts))
    os.system('dot -Tpng -o %s %s' % (png_ltl, filename_ltl))
    os.system('dot -Tpng -o %s %s' % (png_final, filename_final))
Exemple #2
0
def _getBadEdges(system, ltl, record_exp_list=[]):
    ts = system.transition_system
    buchi_ts = Buchi.tsToGenBuchi(ts, record_exp_list)
    buchi_ltl = Buchi.ltlToBuchi(ltl)
    (buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)

    field_list = [state.field for state in ts.state_list]
    # Stage 1: generate all bad edges
    # 得到所有的坏边
    bad_edges = list()
    other_edges = list()
    for edge in buchi_final.edge_list:
        if not buchi_final.getStateAcc(edge.src):
            try:
                src_index_ts = pairs[edge.src][0]
                dst_index_ts = pairs[edge.dst][0]
                if ts.num_state == src_index_ts:
                    # this is the initial node, skip
                    continue
                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_index_ts, dst_index_ts)
                ltl_req = _getLTLReq(buchi_ltl, src_index_ltl, dst_index_ltl)
                if buchi_final.getStateAcc(edge.dst):
                    bad_edges.append(
                        BadEdge(src_index_ts, dst_index_ts, src_index_ltl,
                                dst_index_ltl, src_field, dst_field, action,
                                ltl_req))
                else:
                    other_edges.append(
                        BadEdge(src_index_ts, dst_index_ts, src_index_ltl,
                                dst_index_ltl, src_field, dst_field, action,
                                ltl_req))
            except IndexError:
                # if this happen, this means that the system has already been in wrong state from the initial state
                raise Exception(
                    'The property is violated in the initial state, please try a different initial state'
                )

    return bad_edges, other_edges
class S(IoTSystem):
    ac = AirConditioner()


ac = S()
ltl = '!G(ac.thermostatGreaterThan70 & ac.thermostatLessThan75)'
result = generateFixForSafety(ac, ltl)
print(result)
for edge_result in result:
    print(edge_result[0][0].log())

field_list = [state.field for state in ac.transition_system.state_list]

ts = ac.transition_system
buchi_ts = Buchi.tsToGenBuchi(ts)
buchi_ltl = Buchi.ltlToBuchi(ltl)
(buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)


def generateStatement(crit_value_list, event_list, template):
    """
    return a set of statements that will cover all edges from a set of events for numeric variable in channel
    :param crit_value_list: list of numeric
    :param event_list: list of string
    :param template: string
    :return:
    """
    crit_value_list = sorted(crit_value_list)
    prefix_crit = crit_value_list[:-1]
    suffix_crit = crit_value_list[1:]
Exemple #4
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
Exemple #5
0
def generateFixForSafety(system, ltl):
    """
    Given a ltl property for a transition system, generate new tap rules to fix them
    :param system: iot system
    :param ltl: the property to be fixed
    :return: a set of new tap rule? new system? list
    """
    result = list()

    ts = system.transition_system
    buchi_ts = Buchi.tsToGenBuchi(ts)
    buchi_ltl = Buchi.ltlToBuchi(ltl)
    (buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)

    field_list = [state.field for state in ts.state_list]
    bad_edges = list()

    # generate all edges to be fixed
    for edge in buchi_final.edge_list:
        if buchi_final.getStateAcc(edge.dst) and not buchi_final.getStateAcc(edge.src):
            try:
                src_index_ts = pairs[edge.src][0]
                dst_index_ts = pairs[edge.dst][0]
                if ts.num_state == src_index_ts:
                    # this is the initial node, skip
                    continue
                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_index_ts, dst_index_ts)
                ltl_req = _getLTLReq(buchi_ltl, src_index_ltl, dst_index_ltl)
                bad_edges.append(BadEdge(src_index_ts, dst_index_ts, src_index_ltl, dst_index_ltl,
                                         src_field, dst_field, action, ltl_req))
            except IndexError:
                # if this happen, this means that the system has already been in wrong state from the initial state
                raise Exception('The property is violated in the initial state, please try a different initial state')

    # find all states in safe cluster
    safe_states_list = buchi_final.getAccStates(None)
    safe_states_list = [field_list[pairs[index][0]] if pairs[index][0] < len(field_list) else []
                        for index in safe_states_list]

    bad_event_edge = list()
    bad_action_edge = list()
    bad_rule = list()

    for edge in bad_edges:
        if '->' in edge.action:
            # this bad edge is an action triggered by a tap rule
            # fix_list1 = list(_fixEdgeByDeleting(edge, system))
            # fix_list2 = list(_fixEdgeByAddingConstraints(edge, system))
            # result.append(fix_list1 + fix_list2)
            rule_name = re.match(r'rule\((?P<rule_name>\w+)\)->[^ ]+', edge.action).group('rule_name')
            bad_action_edge.append(edge)
            if rule_name not in bad_rule:
                bad_rule.append(rule_name)
            # result.append(_fixActionEdge(edge, system))
        else:
            # this bad edge is because of external events
            bad_event_edge.append(edge)
            # result.append(_fixEventEdge(edge, system))

    for edge in bad_event_edge:
        result.append(_fixEventEdge(edge, system))

    for rule_name in bad_rule:
        result.append(_fixActionRule(rule_name, bad_action_edge, safe_states_list, system))


    # return list(itertools.product(*result))
    return result
Exemple #6
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)
Exemple #7
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)
Exemple #8
0
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

AutoTap is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with AutoTap.  If not, see <https://www.gnu.org/licenses/>.
"""

import autotapmc.buchi.Buchi as Buchi

buchi = Buchi.Buchi()

buchi.addAp('p1')
buchi.addAp('p2')

buchi.addState(0, 'State 0', 0)
buchi.addState(1, 'ACC_State 1', 1)
buchi.addState(2, 'State 2', 0)

buchi.setInitState(0)
buchi.addEdge(0, 1, 'p1')
buchi.addEdge(1, 1, 'p1 & p2')
buchi.addEdge(1, 2, 'p2')
buchi.addEdge(2, 1, 'p1 | p2')

(aut, state_map) = buchi.toSpot()
Exemple #9
0
def compareRules(tap_list1, tap_list2, ltl, template_dict):
    """
    To show the differences between tap_list1 and tap_list2
    :param tap_list1:
    :param tap_list2:
    :param ltl:
    :param template_dict:
    :return:
    """
    if ltl == None:
        ltl_formula = '!(0)'
    else:
        ltl_formula = ltl

    crit_value_dict = generateCriticalValue(ltl_formula, tap_list1 + tap_list2)
    exp_t_list, record_exp_list = generateTimeExp(ltl_formula,
                                                  tap_list1 + tap_list2)
    channel_name_list, cap_name_list, tap_list = getChannelList(
        ltl_formula, tap_list1 + tap_list2)

    tap_list1 = tapFormat(tap_list1, crit_value_dict)
    tap_list2 = tapFormat(tap_list2, crit_value_dict)

    new_ltl = ltlFormat(ltl_formula)
    # stage 4: generate system
    channel_dict = generateChannelDict(channel_name_list, crit_value_dict, {},
                                       cap_name_list, template_dict)
    system = _fixPreProcessing(channel_dict=channel_dict,
                               tap_dict={},
                               template_numeric_dict=crit_value_dict,
                               timing_exp_list=exp_t_list)

    ts = system.transition_system
    buchi_ts = Buchi.tsToGenBuchi(ts, record_exp_list)
    buchi_ltl = Buchi.ltlToBuchi(new_ltl)
    (buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)
    field_list = [state.field for state in ts.state_list]

    result = list()
    for edge in buchi_final.edge_list:
        if not buchi_final.getStateAcc(edge.src):
            try:
                src_index_ts = pairs[edge.src][0]
                dst_index_ts = pairs[edge.dst][0]
                if ts.num_state == src_index_ts:
                    # this is the initial node, skip
                    continue
                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_index_ts, dst_index_ts)
                ltl_req = _getLTLReq(buchi_ltl, src_index_ltl, dst_index_ltl)

                beh1 = checkTapListBehavior(tap_list1, system, src_field,
                                            action)
                beh2 = checkTapListBehavior(tap_list2, system, src_field,
                                            action)

                condition = [
                    ap for ap in system.getApList(src_field)
                    if '@' not in ap and 'trigger' not in ap
                ]
                condition = condition + [
                    '!' + ap for ap in system.getAllAp() if '@' not in ap
                    and 'trigger' not in ap and ap not in condition
                ]

                if beh1 != beh2:
                    result.append((action, condition, (beh1, beh2)))

            except IndexError:
                # if this happen, this means that the system has already been in wrong state from the initial state
                raise Exception(
                    'The property is violated in the initial state, please try a different initial state'
                )

    new_result = list()
    for action, condition, beh_tup in result:
        new_condition = [textToformula(cond) for cond in condition]
        new_beh_0 = None if not beh_tup[0] else textToformula(beh_tup[0])
        new_beh_1 = None if not beh_tup[1] else textToformula(beh_tup[1])
        new_result.append(
            (textToformula(action), new_condition, (new_beh_0, new_beh_1)))
    return new_result
Exemple #10
0
"""

from autotapmc.channels.Weather import Weather
from autotapmc.channels.GarageDoor import GarageDoor
from autotapmc.model.IoTSystem import IoTSystem
from autotapmc.model.Tap import ESERule
import autotapmc.buchi.Buchi as Buchi


class Test(IoTSystem):
    weather = Weather()
    door = GarageDoor()
    rule = ESERule('weather.startsRaining', 'door.open', 'door.close')


a = Test()
ts = a.transition_system

buchi_ts = Buchi.tsToGenBuchi(ts)
buchi_ltl = Buchi.ltlToBuchi('F (door.open & weather.raining)')

(buchi_final, pairs) = Buchi.product(buchi_ts, buchi_ltl)
buchi_ts.log()
buchi_ltl.log()
buchi_final.log()

group = [s2 for s1, s2 in pairs]

buchi_final.printToGv(group)