What are good algorithms?

Prof. Dr. Mirco Schoenfeld

Recap

Which of your algorithms is the best?

What to compare

Execution of an algorithm often depends on

  • the size of the input
  • hardware capabilities
  • skill of the programmer

What to compare

We could compare…

  • Running time
  • Memory requirement
  • Number of hard-disc accesses
  • Program size
  • Power consumption
  • Degree of parallelization

Räcke (2021)

Capacity

Let’s start looking at memory requirements.

Although this might be less intuitive.

How much memory capacity is required for a computation?

Capacity

Capacity is less important than execution time:

  • memory is cheap
  • we will never run out of space before we run out of time
  • sublinear space is unrealistic: we have at least the capacity of the length of the input available

Capacity

Why do we care about capacity nontheless?

  • some algorithms do require huge amount of space
  • small memory requirements often relate to parallelization
  • algorithms with huge input or on small computers do have sublinear capacity (input: internet graph, or RFID-chips)

Time

So, the more relevant dimension for comparing algorithms is execution time.

Time

Why consider time?

  • time is money
  • solving a problem in \(10^{10000}\) years
    means not being able to solve it.

Time

How can we measure time?

  • number of steps of computation
  • depth of decision diagrams
  • number of iterations
  • types of operations

Time

We need two things to measure time:

A machine model which defines durations of basic operations.

  • Turing machine
  • Random Access Machines
  • Quantum Machines

Actual durations. We get the number of operations a program needs via

  • \(T( x )\) given an input \(x\)
  • \(T( l )\) given an input of length \(l\)

 

Time

Let’s measure some times (Tantau 2016)

static boolean containsZero (String s) {
  for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) ==0) {
      return true;
    }
  }
  return false;
}

Times \(t_1 ... t_6\) for

  • assignments \(( t_1 )\),
  • comparisons \(( t_2 )\),
  • calls to length \(( t_3 )\),
  • calculations of i++ \(( t_4 )\),
  • calls to charAt \(( t_5 )\),
  • calls to return \(( t_6 )\).

Time

\(T( \text{ABCD05} ) = t_1 + 10t_2 + 5t_3 + 4t_4 + 5t_5 + t_6\)

static boolean containsZero (String s) {
  for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) ==0) {
      return true;
    }
  }
  return false;
}

Times \(t_1 ... t_6\) for

  • assignments \(( t_1 )\),
  • comparisons \(( t_2 )\),
  • calls to length \(( t_3 )\),
  • calculations of i++ \(( t_4 )\),
  • calls to charAt \(( t_5 )\),
  • calls to return \(( t_6 )\).

Time

\(T( \text{ABCDEF} ) = t_1 + 13t_2 + 7t_3 + 6t_4 + 6t_5 + t_6\)

static boolean containsZero (String s) {
  for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) ==0) {
      return true;
    }
  }
  return false;
}

Times \(t_1 ... t_6\) for

  • assignments \(( t_1 )\),
  • comparisons \(( t_2 )\),
  • calls to length \(( t_3 )\),
  • calculations of i++ \(( t_4 )\),
  • calls to charAt \(( t_5 )\),
  • calls to return \(( t_6 )\).

Time

\(T( 6 ) = t_1 + 13t_2 + 7t_3 + 6t_4 + 6t_5 + t_6\)

static boolean containsZero (String s) {
  for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) ==0) {
      return true;
    }
  }
  return false;
}

Times \(t_1 ... t_6\) for

  • assignments \(( t_1 )\),
  • comparisons \(( t_2 )\),
  • calls to length \(( t_3 )\),
  • calculations of i++ \(( t_4 )\),
  • calls to charAt \(( t_5 )\),
  • calls to return \(( t_6 )\).

Time

\(T( l ) = t_1 + (2l+1)t_2 + (l+1)t_3 + lt_4 + lt_5 + t_6\)

static boolean containsZero (String s) {
  for (int i = 0; i < s.length(); i++) {
    if (s.charAt(i) ==0) {
      return true;
    }
  }
  return false;
}

Times \(t_1 ... t_6\) for

  • assignments \(( t_1 )\),
  • comparisons \(( t_2 )\),
  • calls to length \(( t_3 )\),
  • calculations of i++ \(( t_4 )\),
  • calls to charAt \(( t_5 )\),
  • calls to return \(( t_6 )\).

Time

Execution time of the simple example:
\(T( l ) = t_1 + (2l+1)t_2 + (l+1)t_3 + lt_4 + lt_5 + t_6\)

Actual time depends on a specific hardware.
But, precise time measurements rather irrelevant.

We want a picture of the general behaviour of the algorithm.

Complexity Classes

We would like to compare complexity of problems.

Complexity classes are sets of related computational problems.

They define bounds for resources of algorithms tailored to a specific machine model

O-Notation

Complexity classes are often expressed using the Big O Notation.

Big O notation is a mathematical notation.

It describes the behavior of a function which is given huge inputs.

O-Notation

In computer science, big O notation is used to classify algorithms.

It describes how their run time or space requirements grow
as the input size grows.

O-Notation

Different algorithms with the same asymptotic growth rate may be represented using the same O notation.

O-Notation

Big O notation is usually used to describe an upper bound on the complexity of an algorithm.

O-Notation

Central Ideas of O notation:

  1. ignore constant factors used in multiplication
  2. only consider large inputs.

O-Notation

Definition of O notation:

Let \(g : \mathbb{N} \to \mathbb{N}\) be a function.

Then, the O-class or order of the function \(O(g)\)
yields the set of all functions \(f : \mathbb{N} \to \mathbb{N}\)

  • for which a constant \(c \gt 0\) and
  • a constant \(n_0 \in \mathbb{N}_0\) exist such that
  • \(f(n) \le c \cdot g(n)\) for all \(n \ge n_0\)

\(O(g)\) is the set of functions that asymptotically grow not faster than \(g\).

Räcke (2021)

O-Notation

\(c \cdot g(n)\) has to
be in highlighted area

Tantau (2016)

O-Notation

Example:

Let \(g(n) = n^2\) and \(f(n) = 3+17n^2\). Then, \(f \in O(g)\).
(With \(c=1000\) and \(n_0=1000\) this holds: \(3+17n^2 \le cn^2\) )

O-Notation

Example:

Let \(g(n) = n^2\) and \(f(n) = 1000\sqrt{n}\). Then, \(f \in O(g)\).
(With \(c=1000\) and \(n_0=0\) this holds: \(1000\sqrt{n} \le cn^2\) )

O-Notation

Example:

Let \(g(n) = n\) and \(f(n) = n^2\). Then, \(f \notin O(g)\).

O-Notation

We often write

  • \(O(n^2)\) instead of ” \(O(g)\) with function \(g(n) = n^2\) “.
  • \(f(n) = O(n^2)\) instead of \(f(n) \in O(n^2)\)
    although the O-notation is not about equality!

O-Notation

Räcke (2021)

O-Notation

Räcke (2021)

O-Notation

Räcke (2021)

O-Notation

Räcke (2021)

O-Notation

Räcke (2021)

O-Notation

Räcke (2021)

O-Notation

Räcke (2021)

O-Notation

\(\begin{aligned} O(1) &\subsetneq O(\log n) \\ &\subsetneq O(\sqrt{n}) \\ &\subsetneq O(n) \\ &\subsetneq O(n \log n) \\ &\subsetneq O(n^2) \\ &\subsetneq O(n^3) \\ &\subsetneq O(2^n) \\ &\subsetneq O(n!) \end{aligned}\)

O-Notation

Up to \(O(n^3)\) is “acceptable”…

O-Notation

Benefits of O notation

  • gives good estimates for large \(n\)
  • an exact analysis might be hard to achieve
  • exact analyses might not be more precise or helpful
  • linear speed up is always possible by using a faster machine

Why again?

Why talking about complexity again?

In the end, we want to utilize theory
to find new algorithmic approaches.

More on that later.

Thanks

https://xkcd.com/2939/

Acknowledgement

Acknowledgement:

This script is inspired by Tantau (2016) and Räcke (2021).

References

Räcke, Harald. 2021. “Lecture Notes to the Lecture Intro to Linear Programming.” TUM. http://www14.in.tum.de/lehre/2021WS/ea/.
Tantau, Till. 2016. Einführung in Die Informatik. Online. https://www.tcs.uni-luebeck.de/de/mitarbeiter/tantau/lehre/lectures/EinfuehrungindieInformatik-2016.pdf.
Back to Lecture Website