Complexiteit
1. Rij van Fibonacci
- neem twee getalen in een rij, bv. “0” en “1”. → `[0, 1]`
- maak het volgende element aan als de som van de vorige twee. Bv. “0 + 1 = 1”. → `[0, 1, 1]`
- herhaal de vorige stap → `[0, 1, 1, 2, 3, 5, …]`
Dit is de Rij van Fibonacci.
Oefening: zet die rij in je hoofd voort!
2. Hersenen
Wat doe jij als je die rij in je hoofd berekend?
- “Werkgeheugen”: vorige twee getalen onthouden.
- “Processor”: je weet hoe je de som vormt.
Wat komt er bij als je de getalen op papier schrijft?
- “Harde schrijf”: uitbesteding van je werkgeheugen, maar trager.
3. Computerarchitectuur
4. Complexiteit
We willen vermijden dat tijdens de uitvoering de processor vastlopt of het geheugen op is.
“Ik heb altijd ofwel te weinig tijd, of te weinig geheugen.”
- De last van een algoritme voor de processor kunnen we inschatten met de “Time Complexity”
- De last van een algoritme voor het werkgeheugen kunnen we inschatten met de “Space Complexity”
Dit zijn theoretische schattingen. Je kan looptijdbeslissingen niet voorspellen (bv. “conditionals” of user input). De complexiteit is dus een benadering; een soort van “worst case” schatting.
Wij gaan dit hier niet doen. Enkele toevallig gevondene bronnen voor geïnteresseerden:
5. Praktische Benadering
5.1. looptijd
We kunnen de looptijd meten, bv. met time.time()
(documentatie):
from time import time tic = time() resultaat = functie(*args, **kwargs) toc = time() looptijd = toc - tic # in seconden
5.2. geheugen
- op windows: gebruik het programma Resource Monitor
- op linux: bv.
htop
(zie hier)
(Noot: er zijn ook enkele python-oplossingen, zie hier)
6. Voorbeeld: Rij van Fibonacci
We kunnen de Rij van Fibonacci op meerdere manieren implementeren. De looptijd hangt duidelijk af van de gekozen algoritme.
- werkbestand van tijdens de les: hier downloaden
# naive implementatie: Fibonacci-rij # Fibonacci-Rij def Fibonacci1(n): # base case if (n == 0) or (n == 1): return n # anders: som van de vorige twee elementen return Fibonacci1(n-1) + Fibonacci1(n-2) def Fibonacci2(n): # base case if (n == 0) or (n == 1): return n rij = [0]*(n+1) # een lege lijst met de lengte n+1 # geef de eerste twee elementen rij[0] = 0 rij[1] = 1 # rij aanvullen for i in range(2, n+1): rij[i] = rij[i-1]+rij[i-2] return rij[-1] # de tijd meten die een functie nodig heeft from time import time looptijden = [] for i in range(40): starttijd = time() fib = Fibonacci1(i) eindtijd = time() print(i, fib, eindtijd-starttijd) looptijden.append(eindtijd-starttijd) import matplotlib.pyplot as PLT PLT.plot(looptijden) PLT.gca().set_xlabel('Fibonacci(n) recursief') PLT.gca().set_ylabel('tijd t (s)') PLT.gca().spines[['top', 'right']].set_visible(False) PLT.gcf().savefig('../img/fibonacci_looptijden.svg', dpi = 100, transparent = False) PLT.show()
vorige les \(\quad\) volgende les