Lecture 002

int pow(int a, int b)
//@requires b>= 0;
  if (b == 0) return 1;
  return pow(a, b-1) *a;

:warning: check what pow(a, b-1) returns when b==0; we certainly want it to return a value other than 1 and a function. The function above will return 1 and exit.

int f(int x, int y)
//@requires y>=0
//@ensures \result == pow(a, b)
  int a = x;
  int b = y;

  int r = 1;
  while (y>1) {
    if (y % 2 == 1) {
      r = x*r;
    x = x*x;
    y = y/2;


@loop_invariant We need to care about:

Looking for Loop Invariant

b e r
2 8 1
4 4 1
16 2 1
In this case, r and b^e is loop invariant.
Loop invariant is a Boolean statement, it was checked before the first iteration of the loop
b e r b^e
2 7 1 128
4 3 2 64
16 1 8 16
In this case r(b^e) is constant

we should always find loop invariant, but finding the interesting one is more important

Why use //@requires ? Because we can debug with them and not using them in run-time.

:warning: loop invariant is checked before the loop guard (the statement in while or for), including the last check when the loop guard is false, so loop invariant always hold at the end of the loop. When it skip loop. loop invariant is also checked.

Proving Loop Invariant is Actually Valid

Operational Reasoning

Operational Reasoning

Operational Reasoning

:warning: the use of word never, always, each, and initially is considered operational reasoning.

Point-to Reasoning

Using first false result of loop guard to infer loop invariant

INIT (LI true initially) and PRES (preserve Loop Invariant)

INIT and PRES Example:

POS(EXIT) (loop guard and LI imply postconditions)

POS After the Loop:

Fixing the bug:

TERM (with operational proof that loop terminates)

Proving loop must terminate:

Proving in Academic Settings









TODO: listen to the beginning of the lecture about 10min

Table of Content