import numpy as np
from scipy.special import factorial
import matplotlib.pyplot as plt
Here we are taking functions two at a time and plotting them to see why each is asymptotically larger than the previous function.
functions = [lambda n: np.ones(n.shape),
lambda n: np.log(n),
lambda n: n,
lambda n: n*np.log(n),
lambda n: n**2 * np.log(n),
lambda n: n ** 3,
lambda n: 2 ** n,
lambda n: factorial(n),
lambda n: n ** n]
labels = ['1',
'log n',
'n',
'n log n',
'n^2 log n',
'n^3',
'2^n',
'n!',
'n^n']
ns = [np.arange(1,1e3),
np.arange(1,1e3),
np.arange(1,1e3),
np.arange(1,10),
np.arange(1,10),
np.arange(1,10),
np.arange(1,10),
np.arange(1,10)]
for i in range(len(functions)-1):
plt.subplot(1,1,1)
plt.plot(ns[i], functions[i](ns[i]), label=labels[i])
plt.plot(ns[i], functions[i+1](ns[i]), label=labels[i+1])
plt.legend(prop={'size': 15})
plt.show()
In this example below, we see that sometimes functions criss-cross at a certain point. So which is larger? Well asymptotically we would like to say that the orange line is larger, because for everything past the first $10$ numbers, it is becomes much more and more greater than the blue line, and so asymptotically we want to say that orange is larger and this is why we define that extra constraint in our mathematical definitions.
n = np.arange(1,12)
plt.figure(figsize=(12,8))
plt.plot(n, n ** 3, label='n^3')
plt.plot(n, 2 ** n, label='2^n')
plt.legend(prop={'size': 15})
plt.show()