# P vs NP

*P vs NP* is one of the greatest and most important yet unsolved problems in [computer science](computer_science.md): it is the question of whether the [computational class](computational_complexity.md) [P](p.md) is equal to class [NP](np.md) or, in simple terms, whether certain problems for which no "fast" solution is known can in fact be solved "fast". This is very important e.g. for algorithms used in [cryptography](cryptography.md). This problem is in fact so important that it's one of the seven Millennium Prize Problems. **There is a million dollar reward for solving this problem**.

It is believed and sometimes relied on that P != NP (in which case P would be a proper subset of NP), but a mathematical proof doesn't exist yet. If it was surprisingly proven that P = NP, there might be practical consequences for cryptography in which most algorithms rely on the problems in question being difficult (slow) to solve -- a proof of P = NP could lead to fast algorithms for breaking encryption, but that is not a certainty, only one of possible scenarios. However any solution to this problem would be revolutionary and ground breaking.

## Explanation

In the context of [computational complexity](computational_complexity.md) of algorithms we talk about different types of algorithm time complexities, i.e. different "speeds" of algorithms. This "speed" doesn't mean actual running time of the algorithm in real life but rather how quickly the running time grows depending on the amount of input data to it (so rather something akin "[scalability](scalability.md)"), i.e. we are interested only in the shape of the function that describes how the amount of input data affects the running time of the algorithm. The types of time complexity are named after mathematical functions that grow as quickly as this dependence, so we have a *constant* time complexity, *logarithmic* time complexity, *linear* time complexity etc.

Then we have classes of computational problems. The classes divide problems based on how "fast" they can be solved.

The class P stands for **polynomial** and is defined as all problems that can be solved by an algorithm run on a **deterministic [Turing machine](turing_machine.md)** (a theoretical computer) with a *polynomial* time complexity.

The class NP stands for **non-deterministic polynomial** and is defined as all problems that can be solved by an algorithm run on a **non-deterministic Turing machine** with a *polynomial* time complexity. I.e. the definition is the same as for the P class with the difference that the Turing machine is non-deterministic -- such a machine is faster because it can make kind of "random correct guesses" that lead to the solution more quickly. Non-deterministic computers are only theoretical (at least for now), computers we have in real life cannot perform such randomly correct guesses. It is known that the solution to all NP problems can be verified in *polynomial* time even by a deterministic Turing machine, we just don't know if the solution can also be found this quickly.

Basically P means *"problems that can be solved quickly"* and NP means *"problems whose solutions can be verified quickly but we don't know if they can also be solved quickly"*.

The question is whether all NP problems are in fact P problems, i.e. whether *all problems that can be verified quickly can also be solved quickly*. It is believed this is not the case.
