Exemple #1
0
def test_prspeed():
    program = parse_pgcl("""
        nat x;
        nat y;
        nat m;
        nat n;
        while ((x + 3 <= n)) {
            if (y < m) {
                { y := y + 1; } [1/2] {
                    y := y + 0;
                }
            } else {
                { x := x + 0; } [1/4] {
                    { x := x + 1; } [1/3] {
                        { x := x + 2; } [1/2] {
                            x := x + 3;
                        }
                    }
                }
            }
            tick(1);
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == '位饾惞. lfp 饾憢. [(x + 3) <= n] * (([y < m] * (((((饾憢)[y/y + 1]) + (tick(1))) * 1/2) + ((((饾憢)[y/y + 0]) + (tick(1))) * (1.0 - 1/2)))) + ([not (y < m)] * (((((饾憢)[x/x + 0]) + (tick(1))) * 1/4) + ((((((饾憢)[x/x + 1]) + (tick(1))) * 1/3) + ((((((饾憢)[x/x + 2]) + (tick(1))) * 1/2) + ((((饾憢)[x/x + 3]) + (tick(1))) * (1.0 - 1/2))) * (1.0 - 1/3))) * (1.0 - 1/4))))) + [not ((x + 3) <= n)] * 饾惞'
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [((x + 3) <= n) & (y < m)] * 1/2 * ((饾憢)[y/y + 1] + tick(1)) + [((x + 3) <= n) & (y < m)] * (1.0 - 1/2) * ((饾憢)[y/y + 0] + tick(1)) + [((x + 3) <= n) & not (y < m)] * 1/4 * ((饾憢)[x/x + 0] + tick(1)) + [((x + 3) <= n) & not (y < m)] * (1/3 * (1.0 - 1/4)) * ((饾憢)[x/x + 1] + tick(1)) + [((x + 3) <= n) & not (y < m)] * ((1/2 * (1.0 - 1/3)) * (1.0 - 1/4)) * ((饾憢)[x/x + 2] + tick(1)) + [((x + 3) <= n) & not (y < m)] * (((1.0 - 1/2) * (1.0 - 1/3)) * (1.0 - 1/4)) * ((饾憢)[x/x + 3] + tick(1))'
Exemple #2
0
def test_zero_conf_parameterized():
    program = parse_pgcl("""
        # Variable free is either 0 or 1. Free=1 means hosts received answer address free. Free=1 means a collision occurred.
        # If free=0 holds on termination, then the host erroneously assumes that address is free.
        # (inital state constraint: free=0).
        nat free;

        # answerReceived = 1 (= 0) if host does (not) receive an answer.
        nat answerReceived;

        # count keeps track of the number of times the host requested an answer.
        # (initial state constraint: count = 0)
        nat count;

        nat maxCount;


        while(count < maxCount & free = 0){
            {answerReceived := 0}[0.8]{answerReceived := 1}
            if(answerReceived=1){
                {free:=1}[0.5]{free:=0}
                count := 0
            }{
                count:=count+1
            }
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [(count < maxCount) & (free = 0)] * (((([0 = 1] * ((((饾憢)[answerReceived/0, free/1, count/0]) * 0.5) + (((饾憢)[answerReceived/0, free/0, count/0]) * (1.0 - 0.5)))) + ([not (0 = 1)] * ((饾憢)[answerReceived/0, count/count + 1]))) * 0.8) + ((([1 = 1] * ((((饾憢)[answerReceived/1, free/1, count/0]) * 0.5) + (((饾憢)[answerReceived/1, free/0, count/0]) * (1.0 - 0.5)))) + ([not (1 = 1)] * ((饾憢)[answerReceived/1, count/count + 1]))) * (1.0 - 0.8))) + [not ((count < maxCount) & (free = 0))] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [((count < maxCount) & (free = 0)) & (0 = 1)] * (0.5 * 0.8) * (饾憢)[answerReceived/0, free/1, count/0] + [((count < maxCount) & (free = 0)) & (0 = 1)] * ((1.0 - 0.5) * 0.8) * (饾憢)[answerReceived/0, free/0, count/0] + [((count < maxCount) & (free = 0)) & not (0 = 1)] * 0.8 * (饾憢)[answerReceived/0, count/count + 1] + [((count < maxCount) & (free = 0)) & (1 = 1)] * (0.5 * (1.0 - 0.8)) * (饾憢)[answerReceived/1, free/1, count/0] + [((count < maxCount) & (free = 0)) & (1 = 1)] * ((1.0 - 0.5) * (1.0 - 0.8)) * (饾憢)[answerReceived/1, free/0, count/0] + [((count < maxCount) & (free = 0)) & not (1 = 1)] * (1.0 - 0.8) * (饾憢)[answerReceived/1, count/count + 1]'
Exemple #3
0
def test_dueling_cowboys_count():
    program = parse_pgcl("""
        # we have a variable player: player=i (i=0 or i=1) means it's player i's turn
        nat player;
        # and a variable shot: shot=0 means the current player did not shoot the opponent. shot=1 means he did
        nat shot;
        nat c;
        # In this model, player 0 wins with a higher probability
        while(shot=0){
            if(player = 0){
                {shot := 1}[0.6]{player := 1}
            }{
                {shot := 1}[0.4]{player := 0}
            }

            c := c + 1
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [shot = 0] * (([player = 0] * ((((饾憢)[shot/1, c/c + 1]) * 0.6) + (((饾憢)[player/1, c/c + 1]) * (1.0 - 0.6)))) + ([not (player = 0)] * ((((饾憢)[shot/1, c/c + 1]) * 0.4) + (((饾憢)[player/0, c/c + 1]) * (1.0 - 0.4))))) + [not (shot = 0)] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [(shot = 0) & (player = 0)] * 0.6 * (饾憢)[shot/1, c/c + 1] + [(shot = 0) & (player = 0)] * (1.0 - 0.6) * (饾憢)[player/1, c/c + 1] + [(shot = 0) & not (player = 0)] * 0.4 * (饾憢)[shot/1, c/c + 1] + [(shot = 0) & not (player = 0)] * (1.0 - 0.4) * (饾憢)[player/0, c/c + 1]'
Exemple #4
0
def test_loop_forever():
    program = parse_pgcl("""
        while(True){skip}
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(tf) == "位饾惞. lfp 饾憢. [True] * ((饾憢)[]) + [not True] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(snf) == '位饾憢. [True] * 1.0 * (饾憢)[]'
Exemple #5
0
def test_unfair_random_walk():
    program = parse_pgcl("""
        nat x;
        while((not x<=0)){
            {x := x+1 }[0.1]{ x := x-1}
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [not x <= 0] * ((((饾憢)[x/x + 1]) * 0.1) + (((饾憢)[x/x - 1]) * (1.0 - 0.1))) + [not (not x <= 0)] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [not x <= 0] * 0.1 * (饾憢)[x/x + 1] + [not x <= 0] * (1.0 - 0.1) * (饾憢)[x/x - 1]'
Exemple #6
0
def test_geometric_monus_2():
    program = parse_pgcl("""
        nat c;
        nat f;
        while(f=1){
            {f := 0}[0.5]{ c := c - 1 + 2}
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [f = 1] * ((((饾憢)[f/0]) * 0.5) + (((饾憢)[c/(c - 1) + 2]) * (1.0 - 0.5))) + [not (f = 1)] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [f = 1] * 0.5 * (饾憢)[f/0] + [f = 1] * (1.0 - 0.5) * (饾憢)[c/(c - 1) + 2]'
Exemple #7
0
def test_branchy():
    code = """
        while (c < 6) {
            {c := 3} [0.8] {c := 7}
            if (c=2) { d:=10 } {d := 20}
            if (f=1) { f:=0 } {f := 1}
        }
    """
    program = parse_pgcl(code)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == '位饾惞. lfp 饾憢. [c < 6] * (((([3 = 2] * (([f = 1] * ((饾憢)[c/3, d/10, f/0])) + ([not (f = 1)] * ((饾憢)[c/3, d/10, f/1])))) + ([not (3 = 2)] * (([f = 1] * ((饾憢)[c/3, d/20, f/0])) + ([not (f = 1)] * ((饾憢)[c/3, d/20, f/1]))))) * 0.8) + ((([7 = 2] * (([f = 1] * ((饾憢)[c/7, d/10, f/0])) + ([not (f = 1)] * ((饾憢)[c/7, d/10, f/1])))) + ([not (7 = 2)] * (([f = 1] * ((饾憢)[c/7, d/20, f/0])) + ([not (f = 1)] * ((饾憢)[c/7, d/20, f/1]))))) * (1.0 - 0.8))) + [not (c < 6)] * 饾惞'
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [(c < 6) & ((3 = 2) & (f = 1))] * 0.8 * (饾憢)[c/3, d/10, f/0] + [(c < 6) & ((3 = 2) & not (f = 1))] * 0.8 * (饾憢)[c/3, d/10, f/1] + [(c < 6) & (not (3 = 2) & (f = 1))] * 0.8 * (饾憢)[c/3, d/20, f/0] + [(c < 6) & (not (3 = 2) & not (f = 1))] * 0.8 * (饾憢)[c/3, d/20, f/1] + [(c < 6) & ((7 = 2) & (f = 1))] * (1.0 - 0.8) * (饾憢)[c/7, d/10, f/0] + [(c < 6) & ((7 = 2) & not (f = 1))] * (1.0 - 0.8) * (饾憢)[c/7, d/10, f/1] + [(c < 6) & (not (7 = 2) & (f = 1))] * (1.0 - 0.8) * (饾憢)[c/7, d/20, f/0] + [(c < 6) & (not (7 = 2) & not (f = 1))] * (1.0 - 0.8) * (饾憢)[c/7, d/20, f/1]'
Exemple #8
0
def test_linear01():
    program = parse_pgcl("""
        nat x;
        while (2 <= x) {
            { x := x - 1; } [1/3] {
                x := x - 2;
            }
            tick(1);
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == '位饾惞. lfp 饾憢. [2 <= x] * (((((饾憢)[x/x - 1]) + (tick(1))) * 1/3) + ((((饾憢)[x/x - 2]) + (tick(1))) * (1.0 - 1/3))) + [not (2 <= x)] * 饾惞'
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [2 <= x] * 1/3 * ((饾憢)[x/x - 1] + tick(1)) + [2 <= x] * (1.0 - 1/3) * ((饾憢)[x/x - 2] + tick(1))'
Exemple #9
0
def test_ber_ert():
    program = parse_pgcl("""
        nat x;
        nat n;
        nat r;
        while (x < n) {
            r := 1 : 1/2 + 0 : 1/2;
            x := x + r;
            tick(1);
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == '位饾惞. lfp 饾憢. [x < n] * ((1/2 * (((饾憢)[r/1, x/x + 1]) + (tick(1)))) + (1/2 * (((饾憢)[r/0, x/x + 0]) + (tick(1))))) + [not (x < n)] * 饾惞'
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [x < n] * 1/2 * ((饾憢)[r/1, x/x + 1] + tick(1)) + [x < n] * 1/2 * ((饾憢)[r/0, x/x + 0] + tick(1))'
Exemple #10
0
def test_complete_binary_tree():
    program = parse_pgcl("""
        nat a;
        nat b;
        nat c;
        nat maxA;
        nat maxB;
        while (a < maxA & b < maxB) {
            {a:=a+1} [0.5] {b := b+1}
            c:=c+1
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [(a < maxA) & (b < maxB)] * ((((饾憢)[a/a + 1, c/c + 1]) * 0.5) + (((饾憢)[b/b + 1, c/c + 1]) * (1.0 - 0.5))) + [not ((a < maxA) & (b < maxB))] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [(a < maxA) & (b < maxB)] * 0.5 * (饾憢)[a/a + 1, c/c + 1] + [(a < maxA) & (b < maxB)] * (1.0 - 0.5) * (饾憢)[b/b + 1, c/c + 1]'
Exemple #11
0
def test_geometric_flipping():
    program = parse_pgcl("""
        nat c;
        nat f;
        nat k;

        while(f=1){
                if(k=0){
                    {f := 0}[0.5]{ c := c +1 };
                    k := 1
                }{
                k :=0
                }
        }
        """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [f = 1] * (([k = 0] * ((((饾憢)[f/0, k/1]) * 0.5) + (((饾憢)[c/c + 1, k/1]) * (1.0 - 0.5)))) + ([not (k = 0)] * ((饾憢)[k/0]))) + [not (f = 1)] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [(f = 1) & (k = 0)] * 0.5 * (饾憢)[f/0, k/1] + [(f = 1) & (k = 0)] * (1.0 - 0.5) * (饾憢)[c/c + 1, k/1] + [(f = 1) & not (k = 0)] * 1.0 * (饾憢)[k/0]'
Exemple #12
0
def test_brp_simple_parameterized():
    program = parse_pgcl("""
        # The number of total packages to send
        nat toSend;

        # Number of packages sent
        nat sent;

        # The maximal number of retransmission tries
        nat maxFailed;

        # The number of failed retransmission tries
        nat failed;

        while(failed < maxFailed & sent < toSend){
            {
                # Transmission of current packages successful
                failed := 0;
                sent := sent + 1;

            }
            [0.9]
            {
                # Transmission not successful
                failed := failed +1;
            }
        }
    """)
    tf = one_loop_wp_transformer(program, program.instructions)
    assert str(
        tf
    ) == "位饾惞. lfp 饾憢. [(failed < maxFailed) & (sent < toSend)] * ((((饾憢)[failed/0, sent/sent + 1]) * 0.9) + (((饾憢)[failed/failed + 1]) * (1.0 - 0.9))) + [not ((failed < maxFailed) & (sent < toSend))] * 饾惞"
    snf = normalize_expectation_transformer(program, tf.body)
    assert str(
        snf
    ) == '位饾憢. [(failed < maxFailed) & (sent < toSend)] * 0.9 * (饾憢)[failed/0, sent/sent + 1] + [(failed < maxFailed) & (sent < toSend)] * (1.0 - 0.9) * (饾憢)[failed/failed + 1]'
Exemple #13
0
    def _summation_snf_to_pysmt_dnf(self, post_expectation):
        """

        Computes and returns a PySMT representation of the disjunctive normal form of the wp-characteristic functional
        of program w.r.t. post_expectation

        :param program: The program text.
        :param post_expectation: The postexpectation.
        :return: The PySMT representation of the disjunctive normal form (pysmt_dnf_loop_execute, pysmt_dnf_loop_terminate), where:
         pysmt_dnf_loop_execute is
         a list of pairs
         (guard, prob_sub_pairs), where prob_sub_pairs is a list of pairs (prob, variable_substitutions). Every two guards guard and guard' in this dnf
         are mutually exclusive, i.e. guard AND guard' is unsatisfiable

         pysmt_dnf_loop_terminate is
         a list of pairs
         (guard, arithmetic_expression). Every two guards guard and guard' in this dnf are mutually exclusive, i.e.
         guard AND guard' is unsatisfiable.
        """

        # parse program and variable initializations using probably

        # retrieve the wp-characteristic functional of the loop (not containing the post-expectation) from probably

        if self._apply_general_wp:
            probably_wp_transformer = general_wp_transformer(self.program)
        else:
            probably_wp_transformer = one_loop_wp_transformer(self.program, self.program.instructions)
        probably_summation_nf = SnfLoopExpectationTransformer(self.program, probably_wp_transformer)

        #logger.info("Program weakest pre-expectation transformer: \n %s \n" % probably_wp_transformer)

        # Set-Up PySMT Variables: For every program variable, we have a corresponding pysmt variable.
        self._pysmt_program_variables = self._setup_variables()
        self._pysmt_program_variables_argument = tuple(self._pysmt_program_variables)

        # Get (guard, probability, substitution, ticks) quadruples
        probably_guards, probably_probs, probably_subs, probably_ticks = zip(*probably_summation_nf.body_tuples())

        # Convert guards and probabilities to pysmt formulae
        # Notice: We simplify the guards here as this reduces trivial conjuncts such as 2=2 that resulting from substitutions.
        # We also simplify the probabilities, e.g. 1 - 4/5   ->   1/5.
        pysmt_guards = list(map(simplify, map(lambda guard:probably_expr_to_pysmt(guard, None, True, self.monus_euf), probably_guards)))
        pysmt_probs = list(map(simplify, map(probably_expr_to_pysmt, probably_probs)))

        # A sub is a list of dicts, where every dict is a map from variables to substitutions
        pysmt_subs = self._get_pysmt_subs(probably_subs)

        pysmt_ticks = list(map(simplify, map(lambda guard:probably_expr_to_pysmt(guard, None, True, self.rmonus_euf, True), probably_ticks)))

        pysmt_summation_nf = list()
        for i in range(0, len(pysmt_guards)):
            pysmt_summation_nf.append((pysmt_guards[i], pysmt_probs[i], pysmt_subs[i], pysmt_ticks[i]))

        logger.debug("PySMT Summmation Normal Form Objects *before* preprocessing (length = %s): \n %s \n" % (
            len(pysmt_summation_nf), pysmt_summation_nf))

        pysmt_summation_nf = self._remove_unsatisfiable_guards(pysmt_summation_nf)

        logger.debug("PySMT Summmation Normal Form Objects *after* preprocessing (length = %s): \n %s \n" % (
            len(pysmt_summation_nf), pysmt_summation_nf))

        # Constraint asserting that all program variables are non-negative
        self.non_negative_constraint = And(GE(var, Int(0)) for var in self._pysmt_program_variables)

        pysmt_dnf_loop_execute = self._get_pysmt_dnf_loop_execute(pysmt_summation_nf)

        # Now deal with (not guard)-part and postexpectation
        pysmt_dnf_loop_terminated \
            = self._get_pysmt_loop_terminated_dnf(probably_wp_transformer, post_expectation)

        return (pysmt_dnf_loop_execute, pysmt_dnf_loop_terminated)