Question 1 (Hard)

Consider the following piece of code.

int foo()
//@ensures ???
{
    int x = 0;
    for (int i = 0; i <= 10; i++)
    //@loop_invariant ???
    {
        x += POW(2, i);
    }
    return x;
}

What is a possible loop invariant we could use to prove the correctness of the loop?

What is a loop invariant we could use for termination? What will the final value of be?

Solution

//@loop_invariant i <= 0 && i <= 11;
//@loop_invariant x == POW(2, i) - 1;

The final value of will be POW(2, 11) - 1

Question 2 (Medium)

Addresses learning objectives (1)(4)

Given the following contracts and function name, write a function which works as expected.

int divmod (int a, int b)
//@requires b != 0;
//@ensures \result[0] * b + \result[1] == a;

Solution

int divmod (int a, int b)
//@requires b != 0;
//@ensures \result[0] * b + \result[1] == a;
{
  return [a / b, a % b];
}

Question 3 (Medium)

Addresses learning objectives (1)(2)(3)(4)(5)(6)

Given the following slowGCD and GCD function, that takes in two non-negative integers and returns the greatest common divisor of them, prove the correctness of GCD, assuming slowGCD is proven correct.

Do so by proving the initialization, preservation, termination, and correctness of the loop invariants in GCD. You can assume basic properties about the greatest common divisor. For example, by the Euclidean Algorithm, .

#use <conio>
#use <util>

int slowGCD(int a, int b)
//@requires 0 <= a && 0 <= b;
{
  if(a == 0 || b == 0)
    return max(a, b);
  //@assert(0 < a && 0 < b);

  int index = 1;
  int high = 1; //Keeps track of highest common divisor

  while(index <= a && index <= b)
  //@loop_invariant 1 <= index;
  //@loop_invariant index <= max(a, b) + 1;
  {
    if(a % index == 0 && b % index == 0) //index is a common divisor
      high = index;
    index++;
  }
  return high;
}

// Note by the Euclidean algorithm
int GCD(int a, int b)
//@requires 0 <= a && 0 <= b;
//@ensures slowGCD(a, b) == \result;
{
  int x = a;
  int y = b;
  while(x != 0 && y != 0)
  //@loop_invariant slowGCD(x, y) == slowGCD(a, b);
  //@loop_invariant 0 <= x && 0 <= y;
  {
    if(x > y)
      x = x - y;
    else
      y = y - x;
  }
  return max(x, y);
}