Esempio n. 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)
Esempio n. 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)
Esempio n. 3
0
    def test_reduce(self):
        """
        Forall(k,m,l) Gb_k_m
        replaced by
        Forall(k,m) Gb_k_m
        """

        b_k_m = _get_is_true('b', 'k', 'm')

        expr = ForallExpr(['k', 'm', 'l'], UnaryOp('G', b_k_m))

        actual_expr = _reduce_quantifiers(expr)
        expected_expr = ForallExpr(['k', 'm'], UnaryOp('G', b_k_m))

        assert str(actual_expr) == str(expected_expr), str(actual_expr)
Esempio n. 4
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
Esempio n. 5
0
    def visit_forall(self, node:ForallExpr):
        #: :type: tuple
        binding_indices_visited = self.dispatch(node.arg1)
        #: :type: Expr
        quantified_expr_visited = self.dispatch(node.arg2)

        return ForallExpr(binding_indices_visited, quantified_expr_visited)
Esempio n. 6
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)
Esempio n. 7
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)
Esempio n. 8
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]
Esempio n. 9
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))
Esempio n. 10
0
def _reduce_quantifiers(expr:ForallExpr) -> Expr:
    """ Remove useless binding indices """
    quantified_signals_finder = QuantifiedSignalsFinderVisitor()
    quantified_signals_finder.dispatch(expr)
    quantified_signals = quantified_signals_finder.quantified_signals

    indices_used = set(chain(*[qs.binding_indices for qs in quantified_signals]))

    return ForallExpr(indices_used, expr.arg2)
Esempio n. 11
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))
Esempio n. 12
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)
Esempio n. 13
0
    def test_strengthen2(self):
        """
        Forall(i) GFa_i -> Forall(j) GF(b_j)
        is left as it is
        """
        a_i, b_j = QuantifiedSignal('a', 'i'), QuantifiedSignal('b', 'j')

        liveness_ass = ForallExpr(['i'], UnaryOp('G', UnaryOp('F', a_i)))
        liveness_gua = ForallExpr(['j'], UnaryOp('G', UnaryOp('F', b_j)))

        property = SpecProperty([liveness_ass], [liveness_gua])

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

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

        actual = liveness_properties[0]
        expected = property
        assert str(actual) == str(
            expected), str(actual) + ' vs ' + str(expected)
Esempio n. 14
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]
Esempio n. 15
0
    def test_strengthen1(self):
        """
        Forall(i) GFa_i -> Forall(j) G(b_j)
        replaced by
        'safety': Forall(j) G(b_j)
        'liveness': []
        """

        a_i, b_j = QuantifiedSignal('a', 'i'), QuantifiedSignal('b', 'j')

        liveness_ass = ForallExpr(['i'], UnaryOp('G', UnaryOp('F', a_i)))
        safety_gua = ForallExpr(['j'], UnaryOp('G', b_j))

        property = SpecProperty([liveness_ass], [safety_gua])

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

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

        actual_guarantees = safety_properties[0].guarantees
        assert str(actual_guarantees) == str([safety_gua]), \
            '\n' + str(actual_guarantees) + '\nvs\n' + str([safety_gua])
Esempio n. 16
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
Esempio n. 17
0
def _fix_indices(value_by_index:dict, expr:Expr):
    """ if 'index' is not in the value_by_index therefore leave it as is """

    if not is_quantified_expr(expr):
        return expr

    newindex_by_oldindex = dict((i, i) for i in _get_indices(expr))
    newindex_by_oldindex.update(value_by_index)

    replaced_expr = _replace_indices(newindex_by_oldindex, expr)

    indices = _get_indices(replaced_expr)
    new_indices = list(filter(lambda i: isinstance(i, str), indices))

    if len(new_indices) == 0:
        return replaced_expr.arg2
    else:
        assert isinstance(expr, ForallExpr)
        return ForallExpr(new_indices, replaced_expr.arg2)
Esempio n. 18
0
def _denormalize(conjunct:Expr) -> list:
    """
    Forall(i) a_i and b_i
    replaced by
    Forall(i) a_i and Forall(i) b_i
    """

    normalized_conjunct = normalize_conjuncts([conjunct])

    if not is_quantified_property(SpecProperty([normalized_conjunct], [])):
        return [normalized_conjunct]

    #: :type: ForallExpr
    forall_expr = conjunct
    quantified_expr = forall_expr.arg2

    conjunctions = _get_conjuncts(quantified_expr)

    return [_reduce_quantifiers(ForallExpr(forall_expr.arg1, c))
            for c in conjunctions]
Esempio n. 19
0
 def assumptions(self):
     return [ForallExpr(['i'],
                        UnaryOp('G', UnaryOp('F',
                                             BinOp('=',
                                                   QuantifiedSignal(self._FAIR_SCHED_NAME, 'i'),
                                                   Number(1)))))]