Пример #1
0
    def test_localize_two_ass_one_gua(self):
        """
        forall(i,j) a_i_j ->  forall(i) b_i
        replaced by
        forall(i,j) (a_i_j ->  b_i)
        """

        a_i_j_is_true, b_j_is_true = _get_is_true('a', 'i',
                                                  'j'), _get_is_true('b', 'j')
        b_i_is_true = _get_is_true('b', 'i')

        prop = SpecProperty([ForallExpr(['i', 'j'], a_i_j_is_true)],
                            [ForallExpr(['j'], b_j_is_true)])

        localized_prop = localize(prop)
        expected_prop_i_j1 = SpecProperty(
            [Bool(True)],
            [ForallExpr(['i', 'j'], BinOp('->', a_i_j_is_true, b_j_is_true))])
        expected_prop_i_j2 = SpecProperty(
            [Bool(True)],
            [ForallExpr(['i', 'j'], BinOp('->', a_i_j_is_true, b_i_is_true))])

        assert str(localized_prop) == str(expected_prop_i_j1) or \
               str(localized_prop) == str(expected_prop_i_j2), \
            str(localized_prop)
Пример #2
0
    def test_strengthen3(self):
        """
        Forall(i,j) GFa_i * GFb_i_j * Gc_i_j -> Forall(k,m) GF(d_k_m) * G(e_k)
        replaced by
        'safety':   Forall(i) Gc_i_j  ->  Forall(k) G(e_k)
        'liveness': Forall(i,j) GFa_i * GFb_i_j * Gc_i  ->  Forall(k,m) GF(d_k_m)
        """
        a_i, b_i_j, c_i_j = _get_is_true('a', 'i'), _get_is_true(
            'b', 'i', 'j'), _get_is_true('c', 'i', 'j')
        ass = ForallExpr(['i', 'j'],
                         BinOp(
                             '*', UnaryOp('G', UnaryOp('F', a_i)),
                             BinOp('*', UnaryOp('G', UnaryOp('F', b_i_j)),
                                   UnaryOp('G', c_i_j))))

        d_k_m = _get_is_true('d', 'k', 'm')
        e_k = _get_is_true('e', 'k')
        gua = ForallExpr(['k', 'm'],
                         BinOp('*', UnaryOp('G', UnaryOp('F', d_k_m)),
                               UnaryOp('G', e_k)))

        property = SpecProperty([ass], [gua])
        safety_properties, liveness_properties = strengthen(
            property, self._get_converter())

        #lazy..
        print('safety_properties', safety_properties)
        assert len(safety_properties) == 1, str(safety_properties)
        assert len(list(chain(*[sp.assumptions
                                for sp in safety_properties]))) == 1
        assert len(list(chain(*[sp.guarantees
                                for sp in safety_properties]))) == 1

        print('liveness_properties', liveness_properties)
Пример #3
0
 def visit_binary_op(self, binary_op:BinOp):
     if binary_op.name == 'W':
         bin_op_expr = BinOp('+',
                             BinOp('U', binary_op.arg1, binary_op.arg2),
                             UnaryOp('G', binary_op.arg1))
         return self.dispatch(bin_op_expr)
     else:
         return super().visit_binary_op(binary_op)
Пример #4
0
    def test_fix_indices_partially_fixed(self):
        a_i_1 = _get_is_true('a', 'i', 1)
        c_0 = _get_is_true('c', 0)

        expr = ForallExpr(['i'], BinOp('*', a_i_1, c_0))
        result = _fix_indices({'i': 2}, expr)

        a_2_1 = _get_is_true('a', 2, 1)
        expected_result = BinOp('*', a_2_1, c_0)

        self.assertEqual(str(result), str(expected_result))
Пример #5
0
    def guarantees(self):
        """ Return G(tok_i -> Fsends_i)
        """
        #TODO: introduce Globally/Finally class
        expr = UnaryOp(
            'G',
            BinOp(
                '->', BinOp('=', QuantifiedSignal(HAS_TOK_NAME, 'i'),
                            Number(1)),
                UnaryOp(
                    'F',
                    BinOp('=', QuantifiedSignal(SENDS_NAME, 'i'), Number(1)))))

        tok_released = ForallExpr(['i'], expr)
        return [tok_released]
Пример #6
0
def and_properties(properties) -> SpecProperty:
    property_expressions = [
        BinOp('->', and_expressions(p.assumptions),
              and_expressions(p.guarantees)) for p in properties
    ]

    return SpecProperty([Bool(True)], [and_expressions(property_expressions)])
Пример #7
0
def normalize_conjuncts(conjuncts:list) -> Expr:
    """ sound, complete
    forall(i,j) a_i_j and forall(i) b_i  ----> forall(i,j) (a_i_j and b_i)
    forall(i) a_i and forall(j) b_j      ----> forall(i) (a_i and b_i)
    """
    if len(conjuncts) == 0:
        return Bool(True)

    if len(conjuncts) == 1 and isinstance(conjuncts[0], Bool):
        return conjuncts[0]

    for e in conjuncts:
        assert isinstance(e, ForallExpr), 'global non-parameterized properties are not supported'

    max_indices = max(conjuncts, key=lambda e: len(e.arg1))
    new_indices = max_indices.arg1

    normalized_underlying_expr = None
    for e in conjuncts:
        old_indices = e.arg1
        new_by_old = dict((o, new_indices[i]) for i, o in enumerate(old_indices))

        new_underlying_e = _replace_indices(new_by_old, e.arg2)

        if normalized_underlying_expr is None:
            normalized_underlying_expr = new_underlying_e
        else:
            normalized_underlying_expr = BinOp('*', normalized_underlying_expr, new_underlying_e)

    normalized_expr = ForallExpr(new_indices, normalized_underlying_expr)
    return normalized_expr
Пример #8
0
    def test_get_conjuncts_and_op(self):
        a, b = Signal('a'), Signal('b')
        conjunction_expr = BinOp('*', a, b)
        conjuncts = _get_conjuncts(conjunction_expr)

        assert len(conjuncts) == 2
        assert a in conjuncts
        assert b in conjuncts
Пример #9
0
    def test_denormalize(self):
        a_i, b_i = _get_is_true('a', 'i'), _get_is_true('b', 'i')

        expr = ForallExpr(['i'], BinOp('*', a_i, b_i))

        denormalized_expressions = _denormalize(expr)
        assert len(denormalized_expressions) == 2, str(
            denormalized_expressions)
Пример #10
0
 def implications(self) -> list:
     expr = UnaryOp(
         'G',
         UnaryOp('F',
                 BinOp('=', QuantifiedSignal(HAS_TOK_NAME, 'i'),
                       Number(1))))
     fair_tok_sched = ForallExpr(['i'], expr)
     return [fair_tok_sched]
Пример #11
0
    def test_fix_indices_main(self):
        expr = parse_expr('Forall(i,j,k,m) (a_i_j_k=1 * b_i_m=1)')

        result = _fix_indices({'i': 1, 'j': 2, 'k': 3}, expr)
        expected_result = ForallExpr(['m'],
                                     BinOp('*', _get_is_true('a', 1, 2, 3),
                                           _get_is_true('b', 1, 'm')))

        self.assertEqual(str(expected_result), str(result))
Пример #12
0
def to_boolean_nusmv(lts: LTS, specification: SpecProperty) -> str:
    nof_state_bits = int(max(1, math.ceil(math.log(len(lts.states), 2))))
    bits_by_state = dict((state, bin_fixed_list(i, nof_state_bits))
                         for (i, state) in enumerate(sorted(lts.states)))

    state_bits = lmap(_ith_state_bit, range(nof_state_bits))

    _assert_no_intersection(state_bits,
                            list(lts.input_signals) + lts.output_signals)

    dot_lines = StrAwareList()
    dot_lines += 'MODULE main'
    dot_lines += 'IVAR'
    dot_lines += [
        '  {signal} : boolean;'.format(signal=s.name)
        for s in lts.input_signals
    ]

    dot_lines += 'VAR'
    dot_lines += ['  {si} : boolean;'.format(si=si) for si in state_bits]

    dot_lines += 'DEFINE'
    dot_lines += [
        '  {out_name} := {formula} ;'.format(out_name=out_name,
                                             formula=_get_formula(
                                                 out_name, out_model,
                                                 bits_by_state))
        for (out_name, out_model) in lts.model_by_name.items()
    ]

    dot_lines += 'ASSIGN'
    for i, sb in enumerate(state_bits):
        sb_init = str(bits_by_state[list(lts.init_states)[0]][i]).upper()

        dot_lines += '  init({sb}) := {init_sb};'.format(sb=sb,
                                                         init_sb=sb_init)

        dot_lines += '  next({sb}) := '.format(sb=sb)
        dot_lines += '    case'

        for (label, next_state) in lts.tau_model.items():
            sb_next = str(bits_by_state[next_state][i]).upper()
            dot_lines += '      {formula} : {next_state};'.format(
                formula=_clause_to_formula(label, bits_by_state),
                next_state=sb_next)

        dot_lines += '    TRUE : FALSE;'  # default: unreachable states, don't care
        dot_lines += '    esac;'

    expr = BinOp('->', and_expressions(specification.assumptions),
                 and_expressions(specification.guarantees))
    expr = WeakToUntilConverterVisitor().dispatch(
        expr)  # SMV does not have Weak until

    dot_lines += 'LTLSPEC ' + AstToSmvProperty().dispatch(expr)

    return '\n'.join(dot_lines)
Пример #13
0
    def test_strengthen2(self):
        """
        Forall(i) GFa_i and G(b_i)  ->  Forall(j) GF(c_j) and G(d_j)
        replaced by
        'liveness': Forall(i) GFa_i and G(b_i)  ->  Forall(j) GF(c_j)
        and
        'safety': Forall(i) G(b_i)  ->  Forall(j) G(d_j)
        """

        a_i, b_i = QuantifiedSignal('a', 'i'), QuantifiedSignal('b', 'i')
        c_j, d_j = QuantifiedSignal('c', 'j'), QuantifiedSignal('d', 'j')

        ass = ForallExpr(['i'],
                         BinOp('*', UnaryOp('G', UnaryOp('F', a_i)),
                               UnaryOp('G', b_i)))
        gua = ForallExpr(['j'],
                         BinOp('*', UnaryOp('G', UnaryOp('F', c_j)),
                               UnaryOp('G', d_j)))

        property = SpecProperty([ass], [gua])

        safety_properties, liveness_properties = strengthen(
            property, self._get_converter())

        assert len(liveness_properties) == 1, str(liveness_properties)
        assert len(safety_properties) == 1, str(safety_properties)

        expected_liveness_gua = ForallExpr(['j'],
                                           UnaryOp('G', UnaryOp('F', c_j)))

        #: :type: SpecProperty
        liveness_prop = liveness_properties[0]
        assert str(liveness_prop.assumptions) == str([ass]), str(liveness_prop)
        assert str(liveness_prop.guarantees) == str([expected_liveness_gua])

        safety_prop = safety_properties[0]
        expected_safety_ass = ForallExpr(['i'], UnaryOp('G', b_i))
        expected_safety_gua = ForallExpr(['j'], UnaryOp('G', d_j))
        expected_safety_prop = SpecProperty([expected_safety_ass],
                                            [expected_safety_gua])
        assert str(expected_safety_prop) == str(safety_prop), str(safety_prop)
Пример #14
0
def _get_log_encoded_expr(signal:QuantifiedSignal, new_sched_signal_name:str, cutoff:int) -> Expr:
    assert len(signal.binding_indices) == 1

    proc_index = signal.binding_indices[0]

    nof_sched_bits = int(max(1, math.ceil(math.log(cutoff, 2))))
    bits = bin_fixed_list(proc_index, nof_sched_bits)

    #TODO: use quantified signal or signal?
    conjuncts = [BinOp('=',
                       QuantifiedSignal(new_sched_signal_name, bit_index),
                       Number(1 if bit_value else 0))
                 for bit_index, bit_value in enumerate(bits)]

    conjunction = and_expressions(conjuncts)

    return conjunction
Пример #15
0
    def test_localize_zero_ass(self):
        """
        true -> forall(i) b_i
        replaced by
        forall(i) (true -> b_i)
        """

        b_i_is_true = _get_is_true('b', 'i')

        prop = SpecProperty([Bool(True)], [ForallExpr(['i'], b_i_is_true)])

        localized_prop = localize(prop)
        expected_prop = SpecProperty(
            [Bool(True)],
            [ForallExpr(['i'], BinOp('->', Bool(True), b_i_is_true))])

        assert str(localized_prop) == str(expected_prop), str(localized_prop)
Пример #16
0
    def test_sched_optimization(self):
        scheduler = InterleavingScheduler()

        forall_expr = scheduler.assumptions[0]  # Forall(i) GFsched_i=1

        instantiated_expr = _instantiate_expr(
            forall_expr, 2, False)  # GFsched_0=1 * GFsched_1=1

        result_expr = _apply_log_bit_optimization('sch', instantiated_expr, 2,
                                                  scheduler)
        expected_expr = BinOp(
            '*', UnaryOp('G', UnaryOp('F', _get_is_true('sch', 0))),
            UnaryOp('G', UnaryOp('F', _get_is_false('sch', 0))))

        result_str = _get_sorted_conjuncts_str(result_expr)
        expected_str = _get_sorted_conjuncts_str(expected_expr)

        self.assertEqual(expected_str, result_str)
Пример #17
0
def localize(property:SpecProperty):
    """ sound, but incomplete
    forall(i) a_i -> forall(j) g_j
    =>
    forall(i) (a_i -> g_i)

    forall(i,j) a_i_j -> forall(k) g_k
    =>
    forall(i,j) (a_i_j -> g_i)
    """

    if not is_quantified_property(property):
        return property

    normalized_ass = normalize_conjuncts(property.assumptions)
    normalized_gua = normalize_conjuncts(property.guarantees)

    binding_indices_ass = _get_indices(normalized_ass)
    binding_indices_gua = _get_indices(normalized_gua)

    if len(binding_indices_ass) > len(binding_indices_gua):
        max_expr, other_expr = normalized_ass, normalized_gua
    else:
        max_expr, other_expr = normalized_gua, normalized_ass

    assert isinstance(max_expr, ForallExpr)

    max_binding_indices = max_expr.arg1

    ass_newindex_by_old = dict((o, max_binding_indices[i]) for i, o in enumerate(binding_indices_ass))
    gua_newindex_by_old = dict((o, max_binding_indices[i]) for i, o in enumerate(binding_indices_gua))

    replaced_ass = _replace_indices(ass_newindex_by_old, normalized_ass)
    replaced_gua = _replace_indices(gua_newindex_by_old, normalized_gua)

    replaced_underlying_ass = replaced_ass.arg2 if is_quantified_expr(replaced_ass) else replaced_ass
    replaced_underlying_gua = replaced_gua.arg2 if is_quantified_expr(replaced_gua) else replaced_gua

    new_gua = ForallExpr(max_binding_indices,
                         BinOp('->', replaced_underlying_ass, replaced_underlying_gua))

    new_property = SpecProperty([Bool(True)], [new_gua])

    return new_property
Пример #18
0
 def visit_binary_op(self, binary_op:BinOp):
     return BinOp(binary_op.name, self.dispatch(binary_op.arg1), self.dispatch(binary_op.arg2))
Пример #19
0
    def test_get_conjuncts_no_conjuncts(self):
        a, b = Signal('a'), Signal('b')
        conjunction_expr = BinOp('+', a, b)
        conjuncts = _get_conjuncts(conjunction_expr)

        assert conjuncts == [conjunction_expr], str(conjunction_expr)
Пример #20
0
    def test_get_conjuncts_recursion(self):
        a, b, c = Signal('a'), Signal('b'), Signal('c')
        conjunction_expr = BinOp('*', a, BinOp('*', b, c))
        conjuncts = _get_conjuncts(conjunction_expr)

        assert len(conjuncts) == 3
Пример #21
0
def expr_from_property(property: SpecProperty) -> Expr:
    return BinOp('->', and_expressions(property.assumptions),
                 and_expressions(property.guarantees))
Пример #22
0
def to_expr(spec_property: SpecProperty) -> Expr:
    return BinOp('->', and_expressions(spec_property.assumptions),
                 and_expressions(spec_property.guarantees))
Пример #23
0
 def assumptions(self):
     return [ForallExpr(['i'],
                        UnaryOp('G', UnaryOp('F',
                                             BinOp('=',
                                                   QuantifiedSignal(self._FAIR_SCHED_NAME, 'i'),
                                                   Number(1)))))]
Пример #24
0
def _get_is_value(signal_name: str, value: Number, *binding_indices):
    if len(binding_indices) == 0:
        signal = Signal(signal_name)
    else:
        signal = QuantifiedSignal(signal_name, *binding_indices)
    return BinOp('=', signal, value)