In this section, we discuss some time complexity ideas at a higher, more abstract level.
Decision Problems
A decision problem is a problem which takes an input (called an instance) and outputs either a “Yes” or a “No”. We typically denote a decision problem as for the problem, and for the instance.
Note that in a decision problem, we only ask for the solution - we don’t ask how to find the solution.
Example: Decision Problem
: Given two numbers, if their product more than 20?
- If , then .
- If , then .
Now, given a decision problem and an instance such that , a proof (witness) is evidence of this fact. Two notes about witnesses:
- does not necessarily mean we can easily find a witness/proof showing it is true.
- Presenting an invalid witness doesn’t necessarily mean that .
Example: Proofs and Witnesses
: Given a set, does there exist a subset which adds to 0?
If , then with proof .
Note that given a problem that is a non-decision problem, it’s always possible to rephrase it into a decision problem which is just as hard.
P and NP
Suppose we’re running an algorithm on a deterministic Turing Machine, basically your average everyday computer.
Then, an algorithm taking an input of size runs in Polynomial Time if the worst-case time complexity is for some . In other words, the time complexity has an upper bound which can be given as a polynomial.
The set is the set of all decision problems which have polynomial time algorithms which can make the decision:
- If , then the algorithm outputs “Yes”.
- If , then the algorithm outputs “No”.
Example: Polynomial Time Algorithms
Some polynomial time algorithms are given as follows:
Given a list of length , is it sorted?
We can iterate and check if in time.
Given a graph, two vertices and positive integer , does there exist a path from to with length ?
We can run the shortest path algorithm, and see if the shortest path’s length is .
Note that there are problems where we don’t know if there is an algorithm to solve it on polynomial time. For these problems, we cannot say if they are in or not, as we simply do not know.
Now suppose we’re running an algorithm on a non-deterministic Turing Machine, a theoretical machine that can test many ( many) paths, or change to several states simultaneously. By virtue of the machine being more powerful, it can solve more problems faster than a deterministic machine.
The set is the set of all decision problems which can be solved using a non-deterministic Turing Machine in Polynomial Time. More formally, formally, we say if there is a verifier taking an instance and potential witness , running in polynomial time such that:
- If then there exists a witness.
- If then is not a witness.
Note that the converse of these statements does not necessarily have to be true. In other words, our verifier just needs to tell us if a potential witness is a solution or not.
Intuitively, because non-deterministic Turing Machines can explore every possible state at once, they are bottlenecked by the verification of the solution.
Example: NP Problems
Some non-polynomial time algorithms are given as follows:
Given a set of integers , is there a subset that adds to 0? Given the list and any subset , we can check if the sum of elements in the subset is 0 in linear time.
Given a set of integers, is one of them ? Given a set and any particular integer , the verifier could just ignore the witness entirely and solve the problem in linear time.
because there exists an element .
because there exists an element .
because there does not exist an element .
This is a really important distinction! The verifier doesn’t necessarily have to be “verifying” the witness itself.
Given a partially filled sudoku board, does there exist a solution? Given a partially filled board and potential solution , our verifier can check if is a solution.
Note that from this example, it’s the case that as we could just set the verifier to solve any problem in polynomial time. However, there are many problems in that we don’t know are in !
This brings us to a major question in Computer Science:
Polynomial Reducibility
Part of the problem in the question relates to a concept known as polynomial reducibility.
Let us have two decision problems, denoted and . We say that is polynomially reducible to , if there exists a polynomial-time function that can transform instances of into - more forally, . In the case that is polynomially reducible to , we denote this as
Given two problems that are polynomial reducible, we can show that by using some theoretical algorithm solving one of them, we can solve the other problem in polynomial time. Consider the following example.
Example: Polynomially Reducible Problems
Consider the two problems:
ORACLE(S,x)
: Is there a subset of whose sum is ?SUMZERO(S)
: Does have a nonempty subset which adds to 0?We can use the
ORACLE
function to solveSUMZERO
as follows:def sumzero(S): for x in S: if ORACLE(S, x): return True return False
As we can solve
SUMZERO
in a polynomial time algorithm usingORACLE
, we’ve shown that the two problems are polynomially reducible to each other!
Polynomial reduction is especially important in , as if we can show that two problems are polynomially reducible to each other, then if one can be solved in polynomial time, so can the other! This is an extremely vital argument for showing that problems in are also in .
Though not commonly done, we can also use polynomial reducibility with sets! Given two sets and , we can say that is polynomially reducible to if there exists a polynomial time function such that
So, given some value , if we know that is in set , then it also must be in set . In other words, there exists a function that can map one set to the other.
Consider some examples.
Example: Polynomial Reducibility with Sets
Suppose we have sets such that
To show that these sets are polynomially reducible, we define function as so:
We use this function to show that these sets are polynomially reducible to each other.
- We know that if , then where . Plugging this into , we can see that
- If , then for some . But , so