Complexity nomenclature
H. S. Teoh via Digitalmars-d
digitalmars-d at puremagic.com
Fri Dec 4 11:25:20 PST 2015
On Fri, Dec 04, 2015 at 01:37:06PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:
> On 12/04/2015 11:06 AM, Andrei Alexandrescu wrote:
[...]
> Here's the algebra.
>
> Terms:
>
> 1 = O(1)
> log = O(log n)
> plog = O((log n)^k)
> sqrt = O(sqrt n)
> lin = O(n)
> linlog = O(n * log n)
> linplog = O(n * (log n)^k)
> poly = O(n^k)
> exp = O(2^n)
>
> Ordering:
>
> Terms above are in increasing order.
>
> Summation:
>
> x + y = max(x, y)
>
> Product:
>
> | 1 log plog sqrt lin linlog poly exp
>
> -------+------------------------------------------------------------
> 1 | 1 log plog sqrt lin linlog poly exp
>
> log | log plog plog ? linlog ? poly exp
> plog | plog plog plog ? linplog linplog poly exp
> sqrt | sqrt ? ? lin poly poly poly exp
> lin | lin linlog linplog poly poly poly poly exp
> linlog | linlog linplog linplog poly poly poly poly exp
> poly | poly poly poly poly poly poly poly exp
> exp | exp exp exp exp exp exp exp exp
>
> I've left a few question marks for the tricky cases. Ideas?
[...]
sqrt really belongs under poly, as far as asymptotic behaviour is
concerned. Basically, O(n^j) * O(n^k) for any real j, k > 0 is
asymptotically equal to O(n^(j+k)). Furthermore, O(O(n^j)^k) =
O(n^(j*k)). So you can treat polynomial complexities as a field of real
numbers, where + on the O(...) terms behaves like max(), * behaves like
+, and function composition behaves like ^.
Then exp behaves like an "infinite real", where exp > O(n^k) for all
real k>0. Its inverse, log, therefore, behaves like an "infinitesimal",
where O((log n)^k) for all real k>0 is less than O(n^k) for all real
k>0. (Yes, even O(n^(1/1000000)) will eventually outgrow O(log n).)
The log powers behave like "intermediate infinitesimals", where you have
O((log n)^j) < O((log n)^k) for all positive real j < k.
So these O-terms behave approximately like real numbers (poly) enhanced
with infinite quantities (exp and its derivations) and infinitesimal
quantities (log and its derivations), they follow the usual laws of
arithmetic. Therefore,
O(n^k) * O(log n)
can be treated as the equivalent of a real number k + an infinitesimal
L, such that k < (k+L) < k+j for all real j>0. In other words,
O(n) < O(n * log n) < O(n^(1+k)) for all k>0.
(Yes, even O(n^1.00000000001) will eventually outgrow O(n*log n). O(log
n) behaves like an infinitesimal.)
The nice thing about this is that you can simplify a lot of complicated
O(...) expressions just by applying algebra as described above on the
analogous {real + infinities + infinitesimals} system. Ordering
relations are preserved (for the most part -- this only breaks down with
pathological cases like O(sin n) which is unlikely to be ever
encountered). Also, function composition between poly and non-poly
complexities will generally be non-commutative, and mostly will break
the + = max analogy. (But it seems unlikely, in real-world algorithms,
to ever need to worry about the intricacies of exponential-time
algorithms, since generally they are to be avoided where possible.)
So you can get a (mostly) closed algebra just by mapping poly to the
real numbers, and then adding:
L = infinitesimal quantity corresponding to O(log n)
E = infinite quantity corresponding to exp
Various operations inside O(...) are thus mapped:
+ inside O(...) = max(...)
* inside O(...) = + between mapped quantities
O(f(g(n))) = O(f(n)) * O(g(n))
O(1) = 0
Example: is O(n^3*log(n)) better than O(n^2*(log(n))^3)?
Answer:
O(n^3*log(n)) maps to 3 + L, and O(n^2*(log(n))^3) maps to 2 +
L^3. Since L^3 is infinitesimal, (2 + L^3) is very close to 2,
whereas (3 + L) lies slightly above 3. Therefore O(n^3*log(n))
is definitely faster-growing than O(n^2*(log(n))^3).
This algebra leads to various interesting questions like:
- Is there an intermediate complexity that lies between poly and exp?
Yes: since exp is mapped to the infinite quantity E, it follows that
E/2 is still an infinite quantity (even though it's strictly less than
E). E/2 corresponds to E*1/2, which is the composition of exp with
sqrt, so it follows that O(n^k) < O(e^sqrt(n)) < O(e^n) for all real
k>0. (There are, of course, many other possibilities.)
- Similarly, the log powers O((log n)^k) are *always* slower-growing
than any polynomial complexity, because L*k, being still
infinitesimal, will always < j for all real j>0. So even
O((log n)^10000) will not outgrow O(n^1.000000001). Multiplying with a
poly function preserves this relationship:
O(n^j * (log n)^k) --> j + L*k < j + m, for all real j,m>0, so
O(n^j * (log n)^k) < O(n^(j+m)) for all j,m>0.
Basically you're just displacing the mapped values by a constant.
T
--
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird. -- D. Knuth
More information about the Digitalmars-d
mailing list