Beispiel #1
0
def z3_expression_to_nusmv(expression, tables=None, other_tables=None):
    z3_to_nusmv = {
        z3p.Z3_OP_AND: ' & ',
        z3p.Z3_OP_ADD: ' + ',
        z3p.Z3_OP_MOD: ' mod ',
        z3p.Z3_OP_EQ: ' = ',
        z3p.Z3_OP_LT: ' < ',
        z3p.Z3_OP_GT: ' > '
    }
    kind = expression.decl().kind()
    if (z3p.is_const(expression)
            and expression.decl().name().startswith('table_')):
        assert tables is not None
        table_name = expression.decl().name()
        assert table_name in tables or table_name in other_tables
        table_expression = tables[
            table_name] if table_name in tables else other_tables[table_name]
        case_expression = 'case '
        for condition, result in table_expression:
            c = z3_expression_to_nusmv(condition, tables)
            r = z3_expression_to_nusmv(result, tables)
            case_expression += '{} : {}; '.format(c, r)
        case_expression += 'esac'
        return case_expression
    elif kind in z3_to_nusmv:
        children = [
            z3_expression_to_nusmv(c, tables) for c in expression.children()
        ]
        return '({})'.format(z3_to_nusmv[kind].join(children))
    elif expression == z3p.BoolVal(True):
        return 'TRUE'
    elif expression == z3p.BoolVal(False):
        return 'FALSE'
    elif kind == z3p.Z3_OP_NOT:
        e = z3_expression_to_nusmv(expression.arg(0))
        return '!({})'.format(e)
    elif z3p.is_const(expression):
        return str(expression)
    elif kind == z3p.Z3_OP_ITE:
        guard = z3_expression_to_nusmv(expression.arg(0))
        then_branch = z3_expression_to_nusmv(expression.arg(1))
        else_branch = z3_expression_to_nusmv(expression.arg(2))
        return '(case {} : {}; TRUE : {}; esac)'.format(
            guard, then_branch, else_branch)
    else:
        raise NotImplementedError(
            'Cannot translate expression {} to nusmv.'.format(expression))
Beispiel #2
0
 def translate_expression(self, e):
     if e == z3p.BoolVal(True):
         return 'TheLTS->MakeTrue()'
     elif e == z3p.BoolVal(False):
         return 'TheLTS->MakeFalse()'
     elif z3p.is_int_value(e):
         return 'TheLTS->MakeVal("{i}", TheLTS->MakeRangeType({i}, {i}))'.format(i=e)
     elif z3p.is_const(e) and e in self.channels:
         return self.translate_channel_reference(e)
     elif z3p.is_const(e):
         return '{}Exp'.format(to_camel_case(e.decl().name()))
     elif e.num_args() == 1:
         return self.translate_unary_expression(e)
     elif e.num_args() == 2 and e.decl().kind() == z3p.Z3_OP_SELECT:
         return self.translate_channel_reference(e)
     elif e.num_args() == 2:
         return self.translate_binary_expression(e)
     elif e.num_args() == 3:
         return self.translate_ternary_expreession(e)
     else:
         raise NotImplementedError("can't translate expression {} with {}".format(e, e.num_args()))
Beispiel #3
0
def z3_expression_to_nusmv(expression, tables=None, other_tables=None):
    z3_to_nusmv = {z3p.Z3_OP_AND: ' & ',
                   z3p.Z3_OP_ADD: ' + ',
                   z3p.Z3_OP_MOD: ' mod ',
                   z3p.Z3_OP_EQ: ' = ',
                   z3p.Z3_OP_LT: ' < ',
                   z3p.Z3_OP_GT: ' > '}
    kind = expression.decl().kind()
    if (z3p.is_const(expression) and
            expression.decl().name().startswith('table_')):
        assert tables is not None
        table_name = expression.decl().name()
        assert table_name in tables or table_name in other_tables
        table_expression = tables[table_name] if table_name in tables else other_tables[table_name]
        case_expression = 'case '
        for condition, result in table_expression:
            c = z3_expression_to_nusmv(condition, tables)
            r = z3_expression_to_nusmv(result, tables)
            case_expression += '{} : {}; '.format(c, r)
        case_expression += 'esac'
        return case_expression
    elif kind in z3_to_nusmv:
        children = [z3_expression_to_nusmv(c, tables) for c in expression.children()]
        return '({})'.format(z3_to_nusmv[kind].join(children))
    elif expression == z3p.BoolVal(True):
        return 'TRUE'
    elif expression == z3p.BoolVal(False):
        return 'FALSE'
    elif kind == z3p.Z3_OP_NOT:
        e = z3_expression_to_nusmv(expression.arg(0))
        return '!({})'.format(e)
    elif z3p.is_const(expression):
        return str(expression)
    elif kind == z3p.Z3_OP_ITE:
        guard = z3_expression_to_nusmv(expression.arg(0))
        then_branch = z3_expression_to_nusmv(expression.arg(1))
        else_branch = z3_expression_to_nusmv(expression.arg(2))
        return '(case {} : {}; TRUE : {}; esac)'.format(guard, then_branch, else_branch)
    else:
        raise NotImplementedError('Cannot translate expression {} to nusmv.'.format(expression))
 def inputs_in_constraints_for_function(self, function_name, table):
     retval = []
     for constraint in self.constraints:
         expressions = [constraint]
         while len(expressions) > 0:
             expression = expressions.pop()
             if not z3p.is_const(expression):
                 if expression.decl().name() == function_name:
                     retval.append(expression)
                 else:
                     for i in range(expression.num_args()):
                         expressions.append(expression.arg(i))
     return retval
 def inputs_in_constraints_for_function(self, function_name, table):
     retval = []
     for constraint in self.constraints:
         expressions = [constraint]
         while len(expressions) > 0:
             expression = expressions.pop()
             if not z3p.is_const(expression):
                 if expression.decl().name() == function_name:
                     retval.append(expression)
                 else:
                     for i in range(expression.num_args()):
                         expressions.append(expression.arg(i))
     return retval
Beispiel #6
0
def selects_in_expression(expression):
    expressions = [expression]
    selects = []
    while len(expressions) > 0:
        expression = expressions.pop(0)
        if z3p.is_const(expression):
            continue
        elif z3p.is_app(expression):
            if expression.decl().kind() == z3p.Z3_OP_SELECT:
                selects.append(expression)
            else:
                for i in range(expression.num_args()):
                    expressions.append(expression.arg(i))
    return selects
Beispiel #7
0
def selects_in_expression(expression):
    expressions = [expression]
    selects = []
    while len(expressions) > 0:
        expression = expressions.pop(0)
        if z3p.is_const(expression):
            continue
        elif z3p.is_app(expression):
            if expression.decl().kind() == z3p.Z3_OP_SELECT:
                selects.append(expression)
            else:
                for i in range(expression.num_args()):
                    expressions.append(expression.arg(i))
    return selects
Beispiel #8
0
def evaluate_expression(expression,
                        symbolic_memory,
                        concrete_memory,
                        tables=None):
    if isinstance(expression, int):
        return expression
    if isinstance(expression, tuple):
        return expression
    if z3p.is_const(expression):
        if z3p.is_bool_or_int_value(expression):
            return expression
        if expression in symbolic_memory:
            return symbolic_memory[expression]
        elif expression.decl().name().startswith('table_'):
            assert expression.decl().name() in tables
            table_expression = tables[expression.decl().name()]
            first_value = table_expression[0][1]
            if first_value.sort() == z3p.IntSort():
                last_else = z3p.IntVal(0)
            else:
                last_else = z3p.BoolVal(False)
            if_expression = None
            for conditional, value in table_expression:
                guard = evaluate_expression(conditional, symbolic_memory,
                                            concrete_memory)
                last_else = z3p.If(guard, value, last_else)
            return z3p.simplify(last_else)
        else:
            return concrete_memory[expression]
    elif expression.decl().kind() == z3p.Z3_OP_SELECT:
        if expression in symbolic_memory:
            return symbolic_memory[expression]
        else:
            return concrete_memory[expression]
    else:
        new_args = [
            evaluate_expression(expression.arg(i), symbolic_memory,
                                concrete_memory, tables)
            for i in range(expression.num_args())
        ]
        if expression.decl().kind() == z3p.Z3_OP_AND:
            return z3p.And(*new_args)
        else:
            return expression.decl()(*new_args)
Beispiel #9
0
def evaluate_expression(expression, symbolic_memory, concrete_memory, tables=None):
    if isinstance(expression, int):
        return expression
    if isinstance(expression, tuple):
        return expression
    if z3p.is_const(expression):
        if z3p.is_bool_or_int_value(expression):
            return expression
        if expression in symbolic_memory:
            return symbolic_memory[expression]
        elif expression.decl().name().startswith('table_'):
            assert expression.decl().name() in tables
            table_expression = tables[expression.decl().name()]
            first_value = table_expression[0][1]
            if first_value.sort() == z3p.IntSort():
                last_else = z3p.IntVal(0)
            else:
                last_else = z3p.BoolVal(False)
            if_expression = None
            for conditional, value in table_expression:
                guard = evaluate_expression(conditional, symbolic_memory, concrete_memory)
                last_else = z3p.If(guard, value, last_else)
            return z3p.simplify(last_else)
        else:
            return concrete_memory[expression]
    elif expression.decl().kind() == z3p.Z3_OP_SELECT:
        if expression in symbolic_memory:
            return symbolic_memory[expression]
        else:
            return concrete_memory[expression]
    else:
        new_args = [evaluate_expression(expression.arg(i), symbolic_memory, concrete_memory, tables)
                    for i in range(expression.num_args())]
        if expression.decl().kind() == z3p.Z3_OP_AND:
            return z3p.And(*new_args)
        else:
            return expression.decl()(*new_args)
Beispiel #10
0
    def __init__(self, name, locations, initial_location, transitions, variables=None, initial_values=None, input_channels=None, output_channels=None, tables=None, variable_ranges=None, output_channel_ranges=None, compassion=None, justice=None):
        """ Every node represents a control location and has a unique name.
            Transitions are of the form (soruce, channel[, channel expression], guard, update, target)
            where source and target must be automaton control locations,
            channel an input or output channel,
            channel expression is there if the channel is an output one,
            guard is a z3 boolean expression,
            update is a pair (variable, expression).
        """
        super(SymbolicAutomaton, self).__init__()
        self.name = name
        self.variables = variables if variables is not None else []
        self.transitions = transitions
        self.initial_values = initial_values if initial_values is not None else []
        self.initials = {}
        for v, value in zip(self.variables, self.initial_values):
            self.initials[v] = value
        assert len(self.variables) == len(self.initial_values), "# of initial values should match # of variables: variables {}, initials: {}".format(self.variables, self.initial_values)

        self.variable_initial_value = dict(zip([str(v) for v in self.variables],
                                               self.initial_values))
        # TODO change this to work with uninitialized variables
        # change variables input to include initial values
        self.input_channels = input_channels if input_channels is not None else []
        self.output_channels = output_channels if output_channels is not None else []
        # add channel with unit type unit can be an mtype with just one symbol

        for l in locations:
            self.add_node(l)

        for transition in transitions:
            channel_expression = []
            # if it is an input transition, there is no expression for the message to send
            if len(transition) == 6:
                name, source, channel, guard, update, target = transition
                assert channel not in self.output_channels, "Output channel {} used in input transition {}".format(channel, transition)
                kind = 'input'
            # output transitions
            elif len(transition) == 7:
                name, source, channel, channel_expression, guard, update, target = transition
                assert channel not in self.input_channels, "Input channel {} used in output transition {}".format(channel, transition)
                kind = 'output'

            # internal transitios
            elif len(transition) == 5:
                name, source, guard, update, target = transition
                channel = None
            assert source in locations and target in locations, transition
            assert (channel in self.input_channels or
                    channel in self.output_channels or
                    channel is None), transition
            if channel is None:
                kind = 'internal'
            if name is None:
                name = 't_{}'.format(self.number_of_edges())
            self.add_edge(source, target,
                          channel=channel,
                          channel_expression=channel_expression,
                          guard=guard,
                          update=update,
                          name=name,
                          kind=kind,
                          automaton=self)
        assert initial_location in self.nodes()
        self.initial_location = initial_location
        self.tables = {} if tables is None else tables

        self.channel_edges = {}
        self.update_channel_edges()
        self.changes = []
        self.transition_variables = {}
        self.update_transition_variables()
        self.variable_ranges = {} if variable_ranges is None else variable_ranges
        self.output_channel_ranges = {} if output_channel_ranges is None else output_channel_ranges
        for v in self.variables:
            if v.sort() == z3p.IntSort():
                assert v in self.variable_ranges, "No range declared for {}".format(v)
        for variable, variable_range in self.variable_ranges.items():
            assert variable in self.variables, "Variable {} was not declared".format(variable)
            assert variable.sort() == z3p.IntSort()
            assert isinstance(variable_range, tuple) and len(variable_range) == 2
            assert isinstance(variable_range[0], int)
            assert isinstance(variable_range[1], int)
            assert variable_range[0] <= variable_range[1]
        for output_channel_or_field, output_channel_range in self.output_channel_ranges.items():
            if not z3p.is_const(output_channel_or_field) and output_channel_or_field.decl().kind() == z3p.Z3_OP_SELECT:
                assert output_channel_or_field.arg(0) in self.output_channels
            else:
                assert output_channel_or_field in self.output_channels
            # assert output_channel.sort() == z3p.IntSort()
            assert isinstance(output_channel_range, tuple) and len(output_channel_range) == 2
            assert isinstance(output_channel_range[0], int)
            assert isinstance(output_channel_range[1], int)
            assert output_channel_range[0] < output_channel_range[1]
        if compassion is not None:
            self.compassion = compassion
        else:
            self.compassion = []
        if justice is not None:
            self.justice = justice
        else:
            self.justice = []