COMP3010: Algorithm Theory and Design

Daniel Sutantyo,  Department of Computing, Macquarie University

2.0 - Algorithm Correctness

Summary of Week 1

2.0 - Algorithm Correctness

  • Problems and Algorithms
    • Input and Output
  • Complexity analysis
    • RAM model of computation
    • worst-case, average-case, best-case
    • Complexity notations (\(O, \Omega, \Theta\))
  • What we're doing this week is pretty independent to last week

2.0 - Algorithm Correctness

// Add the following to your total score:
// - if you are 30 years or younger, give yourself 8 points
// - if you are aged between 30 and 39, give yourself 7 points
// - if you are aged between 40 and 59, give yourself 5 points
// - if you are 60 years or older, give yourself 4 points

if (age <= 30)
  points += 8
if (age < 40)
  points += 7
if (age < 60)
  points += 5
else
  points += 4
  

2.0 - Algorithm Correctness

year = ORIGINYEAR; /* = 1980 */

// Given days = the number of days since 1 January 1980
// work out what year this is

// if number of days > 365
while (days > 365)
{
    // if it is a leap year
    if (IsLeapYear(year))
    {
        // and number of days > 366
        if (days > 366)
        {
            days -= 366;
            year += 1;
        }
    }
    // it is not a leap year
    else
    {
        days -= 365;
        year += 1;
    }
}

2.0 - Algorithm Correctness

year = ORIGINYEAR; /* = 1980 */

// Given days = the number of days since 1 January 1980
// work out what year this is

// if days == some big number
while (days > 365)
{
    // if it is a leap year
    if (IsLeapYear(year))
    {
        // and number of days > 366
        if (days > 366)
        {
            days -= 366;
            year += 1;
        }
    }
    // ok, if it's not a leap year I don't see a problem
    else
    {
        days -= 365;
        year += 1;
    }
}

2.0 - Algorithm Correctness

year = ORIGINYEAR; /* = 1980 */

// Given days = the number of days since 1 January 1980
// work out what year this is

// if days == 366
while (days > 365)
{
    // if it is a leap year and days == 366
    if (IsLeapYear(year))
    {
        // so, we're not going inside this if statement
        if (days > 366)
        {
            days -= 366;
            year += 1;
        }
        // uhh ... what do we do now?
    }
    
    
    // don't look here, bruh, can't help you
    else
    {
        days -= 365;
        year += 1;
    }
}

2.0 - Algorithm Correctness

  • The code in the previous slide is the (not so) infamous Microsoft Zune bug
  • In December 31, 2008, every single 1st Gen Microsoft Zune stopped working 
    • Microsoft official statement: "wait a day please" (it did work fine the day after)

2.0 - Algorithm Correctness

  • Beginning 14 September 30,828, Windows will not accept dates beyond this day and on startup, Windows will complain about "invalid system time". This is because the FILETIME value in Windows, which is a 64-bit value corresponding to the number of 100-nanosecond intervals since 1 January 1601 UTC [sic], will overflow its maximum possible value on that day at 02:48:05.4775807 UTC.

Y2K bug eh?

2.0 - Algorithm Correctness

2.0 - Algorithm Correctness

How do you find errors?

2.0 - Algorithm Correctness

  • Don't make the errors in the first place (seriously)
    • try to write simple and clear program
    • break down the program into different parts (e.g. functions)
  • Unit tests
    • test different parts of the code (e.g. functions), not just the code as a whole
  • Code review
    • sit down with a fellow developer and explain your code

Proving correctness

2.0 - Algorithm Correctness

  • An algorithm is correct if for every input instance it halts with the correct output 
    • unit testing cannot test every possible input, because there's an infinite amount of possibilities
      • i.e. you cannot use unit testing to prove that your algorithm is correct
    • you also cannot use unit testing to determine stopping conditions, you have to work it out yourself
    • ... but of course we still going to use it for your assignments

Proving correctness

2.0 - Algorithm Correctness

Proving correctness

2.0 - Algorithm Correctness

  • Here is a code that will find divisors of n
for(int i = 2; i < N; i++){
  if (N % i == 0)
    System.out.println(i);
}
  • How do you know that it's correct?
    • Does it stop?
    • Does it produce the right answer?
      • you probably think that every time it hits a divisor it's going to print it (the loop always does the same thing)

Proving correctness

2.0 - Algorithm Correctness

  • Here is a code that adds X n times
// X and n are positive integers
int add(int X, int n){
   if (n <= 0)
     return 0;
   return X + add(X,n-1);
}
  • How do you know that it's correct?
    • Does it stop?
    • Does it produce the right answer?
      • you probably convince yourself that it works for n = 1,
      • then you believe that it works for n = 2, etc

Proving correctness

2.0 - Algorithm Correctness

  • Providing a formal proof for the correctness of an algorithm is often a difficult thing to do
    • in COMP3010 we are only going to see how to do this using loop invariants and induction
      • plus,  show that your program actually halts
    • you need to do this somewhat formally, but this is not a maths course, so we are not going to achieve the same level of formality

Proving correctness

2.0 - Algorithm Correctness

  • Even if you cannot write the proof formally, hopefully you can at least explain logically why your code produces the correct solution
    • if your argument is sound, you'll get some marks
    • obviously more marks if get the proof right
  • You will also encounter other methods of proof, e.g. proof by contradiction (somewhat easier)

Proof by contradiction

2.0 - Algorithm Correctness

4

7

4

5

1

3

5

2

3

2

Prim's Algorithm

5

2.0 - Algorithm Correctness

4

5

2

???

Proof by contradiction

Prim's Algorithm

Proving incorrectness

2.0 - Algorithm Correctness

  • You may also be asked to prove that an algorithm is incorrect
  • It is much easier to do:
    • show the logical error
    • or even more easily, find a counterexample
      • Skiena pg 14 has some tips on this, but you may not understand all of it yet (even though it's page 14 ...)

General tips

2.0 - Algorithm Correctness

  • Get some intuition: random testing, find counterexamples
    • see if the program halts (test the base case, e.g. n = 0)
    • see the behaviour on a small input
    • see the behaviour on consecutive runs
    • go find the corner cases (easier said than done)

Why do this?

2.0 - Algorithm Correctness

  • Unless you do research in computer science, you probably aren't going to do these in real life, but it's still good to have some knowledge of what can be done
    • Analogy: Java, what do you know about Maven, Ant, Gradle, JARs
  • Do they proof code correctness in real life?
    • If you're working for Facebook, Twitter, or Ling's Car, probably not
    • If you're writing the software for pacemakers, missile launchers, and self-driving cars, I sure hope so!

Final note: Correctness vs Optimality

2.0 - Algorithm Correctness

3

2

4

1

3

6

3

7

2

  • Go find the spanning tree

2

4

1

6

3

7

Final note: Correctness vs Optimality

2.0 - Algorithm Correctness

2

4

1

6

3

7

  • Is it a search problem? Is it a decision problem? Optimisation? 

3

2

1

3

3

2

Final note: Correctness vs Optimality

2.0 - Algorithm Correctness

  • Obviously the correctness of the algorithm depends on what the problem is
  • For example, if you need to prove the correctness of a search algorithm, don't try to prove that it can produce an optimal answer
    • Is there a path between A and B?
    • What is the shortest path between A and B?

Coming up next ...

2.0 - Algorithm Correctness

  • Induction
  • Using induction to prove correctness of recursive algorithm
  • Loop invariant
  • Using loop invariant to prove correctness of iterative algorithm (loops)