Exemple #1
0
def relaxed_program(prog: syntax.Program) -> syntax.Program:
    new_decls: List[syntax.Decl] = [d for d in prog.sorts()]

    actives: Dict[syntax.SortDecl, syntax.RelationDecl] = {}
    for sort in prog.sorts():
        name = prog.scope.fresh('active_' + sort.name)
        r = syntax.RelationDecl(name, arity=[syntax.UninterpretedSort(sort.name)],
                                mutable=True, derived=None, annotations=[])
        actives[sort] = r
        new_decls.append(r)

    # active relations initial conditions: always true
    for sort in prog.sorts():
        name = prog.scope.fresh(sort.name[0].upper())
        expr = syntax.Forall([syntax.SortedVar(name, None)],
                             syntax.Apply(actives[sort].name, [syntax.Id(name)]))
        new_decls.append(syntax.InitDecl(name=None, expr=expr))

    for d in prog.decls:
        if isinstance(d, syntax.SortDecl):
            pass  # already included above
        elif isinstance(d, syntax.RelationDecl):
            if d.derived_axiom is not None:
                expr = syntax.relativize_quantifiers(actives, d.derived_axiom)
                new_decls.append(syntax.RelationDecl(d.name, d.arity, d.mutable, expr,
                                                     d.annotations))
            else:
                new_decls.append(d)
        elif isinstance(d, syntax.ConstantDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.FunctionDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.AxiomDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.InitDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.DefinitionDecl):
            assert not isinstance(d.body, syntax.BlockStatement), \
                "relax does not support transitions written in imperative syntax"
            mods, expr = d.body
            expr = syntax.relativize_quantifiers(actives, expr)
            if d.is_public_transition:
                guard = syntax.relativization_guard_for_binder(actives, d.binder)
                expr = syntax.And(guard, expr)
            new_decls.append(syntax.DefinitionDecl(d.is_public_transition, d.num_states, d.name,
                                                   params=d.binder.vs, body=(mods, expr)))
        elif isinstance(d, syntax.InvariantDecl):
            expr = syntax.relativize_quantifiers(actives, d.expr)
            new_decls.append(syntax.InvariantDecl(d.name, expr=expr,
                                                  is_safety=d.is_safety, is_sketch=d.is_sketch))
        else:
            assert False, d

    new_decls.append(relaxation_action_def(prog, actives=actives, fresh=True))

    res = syntax.Program(new_decls)
    res.resolve()  # #sorrynotsorry
    return res
Exemple #2
0
def p_decl_relation_derived(p: Any) -> None:
    'decl : DERIVED RELATION id arity annotations COLON expr'
    p[0] = syntax.RelationDecl(p.slice[2],
                               p[3].value,
                               p[4],
                               mutable=True,
                               derived=p[7],
                               annotations=p[5])
Exemple #3
0
def p_decl_relation(p: Any) -> None:
    'decl : mut RELATION id arity annotations'
    p[0] = syntax.RelationDecl(p.slice[2],
                               p[3].value,
                               p[4],
                               mutable=p[1],
                               derived=None,
                               annotations=p[5])
 def _generate_active_rels(self, scope: syntax.Scope) -> None:
     for sort in scope.known_sorts():
         active_name = scope.fresh('active_%s' % sort.name)
         # TODO: is there a better way to get Sort out of SortDecl?
         sort_not_decl = syntax.UninterpretedSort(sort.name)
         typechecker.typecheck_sort(scope, sort_not_decl)
         active_rel = syntax.RelationDecl(active_name,
                                          arity=(sort_not_decl, ),
                                          mutable=True)
         self._active_rels_mapping[sort] = active_rel
Exemple #5
0
def p_decl_relation_derived(p: Any) -> None:
    'decl : DERIVED RELATION id arity annotations COLON expr'
    start_tok: Token = p.slice[1]
    name_tok: Token = p[3]
    arity_span: Optional[Span]
    arity: List[syntax.Sort]
    arity_span, arity = p[4]
    annots: List[syntax.Annotation] = p[5]
    derived_defn: syntax.Expr = p[7]

    p[0] = syntax.RelationDecl(name_tok.value, arity, mutable=True, derived=derived_defn,
                               annotations=annots, span=loc_join(start_tok, derived_defn.span))
Exemple #6
0
def active_rels_mapping() -> Mapping[syntax.SortDecl, syntax.RelationDecl]:
    # TODO: should be read from the relaxation / the program, not fixed.
    # TODO: duplicated from relaxed_program()
    actives: Dict[syntax.SortDecl, syntax.RelationDecl] = {}
    prog = syntax.the_program

    for sort in prog.sorts():
        name = 'active_' + sort.name  # prog.scope.fresh('active_' + sort.name)
        r = syntax.RelationDecl(name, arity=[syntax.UninterpretedSort(sort.name)],
                                mutable=True, derived=None, annotations=[])
        actives[sort] = r

    return actives
Exemple #7
0
def p_decl_relation(p: Any) -> None:
    'decl : mut RELATION id arity annotations'
    start_tok: Token
    is_mut: bool
    arity_span: Optional[Span]
    arity: List[syntax.Sort]

    start_tok, is_mut = p[1]
    name_tok: Token = p[3]
    arity_span, arity = p[4]
    annots: List[syntax.Annotation] = p[5]

    span = loc_list([start_tok, name_tok, arity_span] + [a.span for a in annots])

    p[0] = syntax.RelationDecl(name_tok.value, arity, mutable=is_mut, derived=None,
                               annotations=annots, span=span)
Exemple #8
0
def sandbox(s: Solver) -> None:
    ####################################################################################
    # SANDBOX for playing with relaxed traces

    import pickle
    trns: logic.Trace = pickle.load(open("paxos_trace.p", "rb"))

    diff_conjunctions = relaxed_traces.derived_rels_candidates_from_trace(
        trns, [], 1, 3)

    print("num candidate relations:", len(diff_conjunctions))
    for diffing_conjunction in diff_conjunctions:
        # print("relation:")
        # for conj in diffing_conjunction:
        #     print("\t %s" % str(conj))
        print(diffing_conjunction[1])

    derrel_name = syntax.the_program.scope.fresh("nder")
    (free_vars, def_expr) = diff_conjunctions[0]
    def_axiom = syntax.Forall(
        free_vars,
        syntax.Iff(
            syntax.Apply(derrel_name,
                         [syntax.Id(None, v.name) for v in free_vars]),
            # TODO: extract pattern
            def_expr))

    derrel = syntax.RelationDecl(
        tok=None,
        name=derrel_name,
        arity=[syntax.safe_cast_sort(var.sort) for var in free_vars],
        mutable=True,
        derived=def_axiom,
        annotations=[])

    # TODO: this irreversibly adds the relation to the context, wrap
    derrel.resolve(syntax.the_program.scope)
    syntax.the_program.decls.append(
        derrel
    )  # TODO: hack! because RelationDecl.resolve only adds to prog.scope
    s.mutable_axioms.extend([
        def_axiom
    ])  # TODO: hack! currently we register these axioms only on solver init

    print("Trying derived relation:", derrel)

    # the new decrease_domain action incorporates restrictions that derived relations remain the same on active tuples
    new_decrease_domain = relaxed_traces.relaxation_action_def(
        syntax.the_program, fresh=False)
    new_prog = relaxed_traces.replace_relaxation_action(
        syntax.the_program, new_decrease_domain)
    new_prog.resolve()
    print(new_prog)

    syntax.the_program = new_prog

    trace_decl = next(syntax.the_program.traces())
    trns2_o = bmc_trace(new_prog, trace_decl, s,
                        lambda s, ks: logic.check_solver(s, ks, minimize=True))
    assert trns2_o is not None
    trns2 = cast(logic.Trace, trns2_o)
    print(trns2)
    print()
    print(
        trns2.as_state(relaxed_traces.first_relax_step_idx(trns2) +
                       1).rel_interp[derrel])
    assert not relaxed_traces.is_rel_blocking_relax(
        trns2, relaxed_traces.first_relax_step_idx(trns2),
        ([(v, str(syntax.safe_cast_sort(v.sort)))
          for v in free_vars], def_expr))

    diff_conjunctions = list(
        filter(
            lambda candidate: relaxed_traces.is_rel_blocking_relax(
                trns2, relaxed_traces.first_relax_step_idx(trns2),
                ([(v, str(syntax.safe_cast_sort(v.sort)))
                  for v in free_vars], def_expr)), diff_conjunctions))
    print("num candidate relations:", len(diff_conjunctions))
    for diffing_conjunction in diff_conjunctions:
        # print("relation:")
        # for conj in diffing_conjunction:
        #     print("\t %s" % str(conj))
        print(diffing_conjunction)

    print()

    assert False
def sandbox(s: Solver) -> None:
    ####################################################################################
    # SANDBOX for playing with relaxed traces
    import pickle
    trns: logic.Trace = pickle.load(open("paxos_trace.p", "rb"))

    diff_conjunctions = relaxed_traces.derived_rels_candidates_from_trace(
        trns, [], 2, 3)

    print("num candidate relations:", len(diff_conjunctions))
    for diffing_conjunction in diff_conjunctions:
        # print("relation:")
        # for conj in diffing_conjunction:
        #     print("\t %s" % str(conj))
        print(diffing_conjunction[1])

    derrel_name = syntax.the_program.scope.fresh("nder")
    (free_vars, def_expr) = diff_conjunctions[0]
    def_axiom = syntax.Forall(
        tuple(free_vars),
        syntax.Iff(
            syntax.Apply(derrel_name,
                         tuple(syntax.Id(v.name) for v in free_vars)),
            # TODO: extract pattern
            def_expr))

    derrel = syntax.RelationDecl(
        name=derrel_name,
        arity=tuple(syntax.safe_cast_sort(var.sort) for var in free_vars),
        mutable=True,
        derived=def_axiom)

    # TODO: this irreversibly adds the relation to the context, wrap
    typechecker.typecheck_statedecl(syntax.the_program.scope, derrel)
    syntax.the_program.decls.append(
        derrel
    )  # TODO: hack! because typecheck_statedecl only adds to prog.scope
    s.mutable_axioms.extend([
        def_axiom
    ])  # TODO: hack! currently we register these axioms only on solver init

    print("Trying derived relation:", derrel)

    # the new decrease_domain action incorporates restrictions that derived relations remain the same on active tuples
    new_decrease_domain = relaxed_traces.relaxation_action_def(
        syntax.the_program, fresh=False)
    new_prog = relaxed_traces.replace_relaxation_action(
        syntax.the_program, new_decrease_domain)
    typechecker.typecheck_program(new_prog)
    print(new_prog)

    syntax.the_program = new_prog

    # TODO: recover this, making sure the candidate blocks the trace
    # trace_decl = next(syntax.the_program.traces())
    # trns2_o = bmc_trace(new_prog, trace_decl, s, lambda s, ks: logic.check_solver(s, ks, minimize=True))
    # assert trns2_o is None

    # migrated_trace = load_relaxed_trace_from_updr_cex(syntax.the_program, s)
    import pickle
    trns2_o = pickle.load(open("migrated_trace.p", "rb"))

    trns2 = cast(logic.Trace, trns2_o)
    print(trns2)
    print()
    assert not relaxed_traces.is_rel_blocking_relax(
        trns2, ([(v, str(syntax.safe_cast_sort(v.sort)))
                 for v in free_vars], def_expr))

    # for candidate in diff_conjunctions:
    #     print("start checking")
    #     print()
    #     if str(candidate[1]) == ('exists v0:node. member(v0, v1) & left_round(v0, v2) '
    #                              '& !vote(v0, v2, v3) & active_node(v0)'):
    #         print(candidate)
    #         assert False
    #         resush = relaxed_traces.is_rel_blocking_relax_step(
    #             trns2, 11,
    #             ([(v, str(syntax.safe_cast_sort(v.sort))) for v in candidate[0]],
    #              candidate[1]))
    #         # res2 = trns2.as_state(0).eval(syntax.And(*[i.expr for i in syntax.the_program.inits()]))
    #
    #         # resush = trns2.as_state(7).eval(syntax.And(*[i.expr for i in syntax.the_program.inits()]))
    #         print(resush)
    #         assert False
    # assert False

    diff_conjunctions = list(
        filter(
            lambda candidate: relaxed_traces.is_rel_blocking_relax(
                trns2, ([(v, str(syntax.safe_cast_sort(v.sort)))
                         for v in candidate[0]], candidate[1])),
            diff_conjunctions))
    print("num candidate relations:", len(diff_conjunctions))
    for diffing_conjunction in diff_conjunctions:
        # print("relation:")
        # for conj in diffing_conjunction:
        #     print("\t %s" % str(conj))
        print(diffing_conjunction[1])

    print()

    assert False
def relaxed_program(prog: syntax.Program) -> syntax.Program:
    new_decls: List[syntax.Decl] = [d for d in prog.sorts()]

    actives: Dict[syntax.SortDecl, syntax.RelationDecl] = {}
    for sort in prog.sorts():
        name = prog.scope.fresh('active_' + sort.name)
        r = syntax.RelationDecl(name,
                                arity=(syntax.UninterpretedSort(sort.name), ),
                                mutable=True)
        actives[sort] = r
        new_decls.append(r)

    # active relations initial conditions: always true
    for sort in prog.sorts():
        name = prog.scope.fresh(sort.name[0].upper())
        expr = syntax.Forall((syntax.SortedVar(name, None), ),
                             syntax.Apply(actives[sort].name,
                                          (syntax.Id(name), )))
        new_decls.append(syntax.InitDecl(name=None, expr=expr))

    for d in prog.decls:
        if isinstance(d, syntax.SortDecl):
            pass  # already included above
        elif isinstance(d, syntax.RelationDecl):
            if d.derived_axiom is not None:
                expr = syntax.relativize_quantifiers(actives, d.derived_axiom)
                new_decls.append(
                    syntax.RelationDecl(d.name,
                                        d.arity,
                                        d.mutable,
                                        expr,
                                        annotations=d.annotations))
            else:
                new_decls.append(d)
        elif isinstance(d, syntax.ConstantDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.FunctionDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.AxiomDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.InitDecl):
            new_decls.append(d)
        elif isinstance(d, syntax.DefinitionDecl):
            relativized_def = relativize_decl(d,
                                              actives,
                                              prog.scope,
                                              inline_relax_actives=False)
            new_decls.append(relativized_def)
        elif isinstance(d, syntax.InvariantDecl):
            expr = syntax.relativize_quantifiers(actives, d.expr)
            new_decls.append(
                syntax.InvariantDecl(d.name,
                                     expr=expr,
                                     is_safety=d.is_safety,
                                     is_sketch=d.is_sketch))
        else:
            assert False, d

    new_decls.append(relaxation_action_def(prog, actives=actives, fresh=True))

    res = syntax.Program(new_decls)
    typechecker.typecheck_program(res)  # #sorrynotsorry
    return res