Usually in AlgorithmAnalysis we are looking for upper bounds on cost, as in "Algorithm X solves problem Y in no more than O(n^{22/7}) time in the worst case." Upper bounds are useful when we want to advertise that our algorithm is good. But what if we want to argue that no other algorithm can be better, or perhaps that some problem is so hard that we can't possibly hope to find a good solution to it?

For this we need a **lower bound**. Lower bounds come in two flavors:

A lower bound on an

*algorithm*is just a big-Omega bound on its worst-case running time. "I don't know exactly how long Bogosort takes in general, but I can prove its worst-case time is Ω(n^{2})."A lower bound on a

*problem*is a big-Omega bound on the worst-case running time of*any*algorithm that solves the problem:"Any comparison-based sorting routine takes Ω(n log n) time." (True; see ComparisonBasedSortingLowerBound.)

"There is an ε > 0 such that any algorithm for IndependentSet takes Ω((1+ε)

^{n}) time." (Might be true. Fame and fortune await anyone who can prove it. See PvsNp.)

# 1. Information-theoretic lower bounds

Most algorithms have to read all of their input to produce the correct output: this takes Ω(n) time.

If there are m possible outputs for inputs of size n and each step yields O(1) bits of information, then we need to take Ω(m) steps. This is the basis of the ComparisonBasedSortingLowerBound.

In general, if we can show that executions that take less than T time can't distinguish between inputs A and B for which f(A) ≠ f(B), then T is a lower bound on correct implementations.

# 2. Lower bounds by reduction

Suppose we already have a lower bound S(n) on some problem A, and that there is a reduction from A to some other problem B. Formally, a reduction is a function f such that A(x) = B(f(x)). Let T_{f}(n) be an upper bound on the time to compute f(x) when |x| = n, and let T_{B}(n) be an upper bound on the time to compute B(x) when |x| = n. Then computing A(x) as B(f(x)) with |x| = n takes time at most T_{f}(n) + T_{B}(T_{f}(n)). (The odd second term comes from the fact that T_{f}(n) is an upper bound on the length of the output of f(x); note that we are also assuming here that T_{B} is nondecreasing.)

An important special case of this is when T_{f} = O(n^{c}) and T_{B} = O(n^{d}) for some c and d. Then T_{f}(n) + T_{f}(T_{B}(n)) = O(n^{c}) + O(n^{cd}) = O(n^{cd}). In words:

- Any problem that has a polynomial-time reduction to a polynomial time problem can be solved in polynomial time.

How do we get lower bounds out of this? Since S(n) ≤ T_{f}(n) + T_{f}(T_{B}(n)), we have T_{B}(n) ≥ T_{f}^{-1}(S(n) - T_{f}(n)). For example:

Suppose there is a reduction f from sorting to some problem B that takes O(n) time and does not examine the elements of the sorting problem. Then B(f(x)) is a comparison-based sorting algorithm if B uses only comparisions, and T

_{B}(n) = Ω(n log n) - O(n) = Ω(n log n).Suppose there is no polynomial-time algorithm for A but there is a polynomial-time reduction from A to B. Then there is no polynomial-time algorithm for B. This is the central idea behind NP-completeness, discussed in PvsNp.

# 3. Can we prove interesting lower bounds?

Lower bounds on problems are the really interesting results, since those are the ones that say that the problem is too hard instead of saying that we are too dumb to come up with a better algorithm. But we aren't very good at proving them; in fact, the comparison-based sorting lower bound is about the only non-trivial lower bound we've got for a traditional algorithmic problem. The difficulty is that it is very hard to write a lower bound proof that covers all possible algorithms, including the ones no one has thought of yet---algorithms are slippery and clever, and there are a lot of them.

So instead we fall back to classifying problems by how hard they appear to be relative to other problems. This classification task is the core of ComputationalComplexityTheory. For many such classes of problems we cannot prove that all the problems in some class are hard, but we can prove that each is hard if and only if all the others are (for an appropriate definition of "hard"). This is not quite as good as a real lower bound, but appears to be the best we can do so far.