Hoares Logic - 2
Hoares Logic - 2
• Consider the code fragment x:=x+1 and suppose that the desired post-
condition is (y = x ).
• {y = x + 1} x:=x+1 {y = x }
• Consider the code fragment x:=2 and
suppose that the desired postcondition is(y =
x ).
Assignment • Our precondition is found by copying the
postcondition y = x over, then re- placing our
axiom occurrence(s) of the variable x with the
expression 2.
example • Formally:
• {y = 2} x:=2 {y = x }
• is an instance of the assignment axiom
• How might we try to prove
• {y > 0} x:=y+3 {x > 3} ?
• Start with the postcondition x > 3 and
apply the axiom:
• {y + 3 > 3} x:=y+3 {x > 3} Assignment
• Then use the fact that y + 3 > 3 is axiom
equivalent to y > 0 to get our result.
• You can always replace predicates by
example
equivalent predicates
Consider Hoare triples involving if/else statements:
{P}
if (B)
S1
if/else, else
condition S2
rule {Q}
When reasoning about if/else statements, once again
it helps to add an intermediate assertion before/after
each line of code. We give the complete structure
below, followed by an explanation of each new line
If-else
{P}
if (g)
{PΛg}
S1;
{Q1}
else
{ P Λ !g }
S2;
{Q2}
{Q1} V {Q2} → {Q}
{Q}
• What do we know immediately after entering the if case
containg S1?
• We know that B is true, or we wouldn’t have entered the
if case.
• We also know that P is true, because we haven’t
executed any code
that could break it.
Explanation • So, we have the assertion P Λ B.
• What do we know immediately after entering the else
case containing S2?
• Again, P must still be true, and B must be false to have
entered the else
case.
• So, we have the assertion P Λ !B
What about Q1 and Q2, and that line with the
arrow (→)? Q1 and Q2 indicate what’s known
after S1 or S2 is executed, respectively.
Because we always enter one case or the
other, we can be sure that Q1 or Q2 will be
Explanation true after executing the entire if/else
statement.
So to conclude that Q always holds true, we
just need to show that Q is true as long as
either Q1 or Q2 is true.
• Written formally, {Q1} V {Q2} → Q. It means
that if (Q1 V Q2) is true, then Q is also true.
In other words, if Q1 is true then Q is true,
and if Q2 is true then Q is true. (If neither Q1
nor Q2 is true, we don’t know anything
about Q – it could be true or false.)
Explanation • Notice that {Q1} V {Q2} → {Q} is the second-
to-last line in our annotated if/else block.
This indicates that to prove that Q always
holds, we need to actually demonstrate that
(Q1 V Q2) → Q.
• As an example, let’s consider writing code to
compute the max of two variables x and y
and store it in a variable m.
• We want to prove that the code works
correctly. It should work for all inputs, so we
Max have the precondition {true}.
compute • The postcondition is { m = max(x,y) }, or
example stated more explicitly, {(m=x Λ x >= y) V (m=y
Λ y >=x) }.
• Try writing this code and annotating it with
the pattern above to prove that Q always
holds
{true}
if (x > y)
{ true Λ x > y } → { x > y }
m = x;
{Q1: m = x Λ x > y }
else
{ true Λ x <= y } → { x <= y }
Explanation m = y;
{Q2: m = y Λ x <= y }
{Q1 V Q2} = { (m = x Λ x >= y) V (m = y Λ x <= y)
}
→ { m = max(x,y) } = {Q}
Thanks/ Xie Xie
• the process we just followed is called forward
reasoning. We simulated the execution of the
program,
considering each statement in the order they
would actually be executed. The disadvantage
Why of forward
reasoning is that the assertions may accumulate
backward a lot of irrelevant facts as you move through the
reasoning program. You don’t know which parts of the
assertions will come in handy to prove
something later and
which parts won’t. As a result, you often end up
listing everything you know about the program.
• This happens in forward reasoning because you
don’t know where you’re trying to go – what
you’re
trying to prove. But when we write a block of
code, we usually have a clear idea of what’s
supposed to
be true after it executes. In other words, we
know the postcondition already, and we want to
prove that
the expected postcondition will indeed hold
true given the appropriate precondition. For this
reason,
backward reasoning is often more useful than
forward reasoning, though perhaps less intuitive