Complexiteit


Home 4BSW1 4BSW2 4MTLAT/4LAT 4MWW1 4MWW2 4NWE2 5BWE 5EWI/5LWI/5WWI1 5WWI2 About

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

Een computer heeft dezelfde componenten:

  • Processor (CPU)
  • Werkgeheugen (RAM)
  • Harde schrijf (HDD)

(doordenker: wat is een GPU eigenlijk?)

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

(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.

# naive implementatie: Fibonacci-rij
def Fibonacci1(n):
    # base case
    if (n == 0) or (n == 1):
        return n

    # normal case
    return Fibonacci1(n-1)+Fibonacci1(n-2)

#  8 [Finished in 118ms]
# 40 [Finished in 57.5s]

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):
    # print (f'het {i}de element in de Rij van Fibonacci is:' \
    #     , Fibonacci1(i))
    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()

fibonacci_looptijden.svg

Date: 2024-02-09 Fri 00:00

Author: Falk Mielke