Inleiding: Wat is Computerwetenschappen?


Net zoals het onmogelijk is precies te definiëren wat wiskunde is of wat biologie is, is het onmogelijk precies vast te leggen wat computerwetenschappen is. Computerwetenschappen vormt dan ook net zoals andere wetenschappen een continuüm dat enerzijds uit een harde kern bestaat maar anderzijds overloopt in andere wetenschappen. In het geval van computerwetenschappen zijn dat voornamelijk de wiskunde, de elektronica, de geografie en zelfs de biologie en de scheikunde. Zo bestaan er wetenschappelijke domeinen met ronkende namen zoals “geografische informatiesystemen”, “computationele biologie” en “computationele scheikunde”.

Los van de voor de hand liggende relevantie van de computerwetenschappen in deze mengdomeinen, vormen de zuivere computerwetenschappen ook een belangrijk vakdomein op zich voor wetenschappers en ingenieurs . Zoals we zullen zien zijn de computerwetenschappen niet alleen belangrijk als hulpmiddel binnen vele wetenschappelijke disciplines (bijvoorbeeld om dingen uit te rekenen) maar worden ze stilaan meer en meer een deel van de onderzoeksmethodologie die binnen deze disciplines gebruikt wordt. Zo spreekt met soms van “in silico” experimenten om aan te duiden dat deze experimenten uitgevoerd worden m.b.v. een computersimulatie (naast de meer klassieke “in vivo”, “in vitro” en “in situ” experimenten die in de biologie respectievelijk uitgevoerd worden binnenin levende organismen, buiten levende organismen of op organismen zoals ze in de natuur voorkomen). De term “in silico” komt van Silicium (Eng: Silicon), één van de basisstoffen die gebruikt worden om de elektronische onderdelen van een computer te bouwen.

Alvorens met het harde werk te beginnen, leiden we deze cursus in door uit te leggen hoe het bestuderen van computerwetenschappen verschilt van het gewone gebruik van een computer bij dagdagelijkse of professionele bezigheden.

Computerwetenschappen vs. Computervaardigheden

Het is belangrijk te begrijpen dat er een hemelsbreed verschil is tussen computerwetenschappen en computervaardigheden. Computervaardigheden gaat over het aanleren van het leren werken met een computer, of meer bepaald, met bepaalde (commerciële) software die op een computer geïnstalleerd staat. Zo zullen vele studenten bij aanvang van deze cursus reeds overweg kunnen met een webbrowser (zoals Safari, Internet Explorer, Firefox, Chrome,…) en met één of ander programma om email te verwerken (zoals bijvoorbeeld MicroSoft Outlook of Apple’s Mail). Andere studenten zullen iets meer gevorderd zijn en zijn misschien wel virtuoos in Ms-Word, Ms-Excel of Ms-Powerpoint. Deze zijn veruit de meest gebruikte programma’s vandaag de dag. Om met zulke programma’s te werken dient men echter geen hogere studies gedaan te hebben of grote wetenschappelijke inzichten te hebben. Dit noemen we dan ook computervaardigheden.

Computerwetenschappen vs. Computer Engineering

Ten tweede is het ook belangrijk een onderscheid te maken tussen computerwetenschappen en “computer engineering”. Computer Engineering gaat over het ontwerpen van computersystemen. Dit betekent dat men kennis van de elektronica en elektrotechniek gebruikt om een nieuw computersysteem te bouwen of te ontwerpen. Dit vakdomein gaat dus over de inwendige samenstelling van een computer. Computer engineering bestaat onder meer uit domeinen als signaalverwerking, regeltechniek, VLSI-ontwerp en het ontwerpen van processoren.

Computerwetenschappen

Toen de eerste computers gebouwd werden kon men daar niet al te veel mee doen. De machines namen typisch hele verdiepingen van universiteitsgebouwen in beslag. Het bedienen ervan (“programmeren”) bestond uit het bedraden van de machine door verschillende onderdelen met mekaar te verbinden. Dat was zeer tijdrovend en leidde tot enorm veel fouten. Pas toen in de jaren 50 en 60 moderne beeldschermen, regelprinters en toetsenborden de intrede deden kwamen de computerwetenschappen pas echt goed van de grond. Op zeer korte tijd ontstond er een enorm grote wetenschap met zeer vele vertakkingen waarvan we er in dit boek enkele zullen belichten vanwege hun relevantie voor wetenschappers en ingenieurs. Zo zijn er bijvoorbeeld de algoritmiek, de numerieke analyse, theorie van programmeertalen, berekenbaarheidstheorie, artificiële intelligentie, netwerken, gedistribueerde systemen en ga zo maar door. De algemene grondstroom van al deze subdisciplines is echter dezelfde: computers meer laten doen op een snellere, goedkopere en correctere wijze. Hoe beter deze subdisciplines floreren, hoe beter de resultaten dus ook toepasbaar zijn in andere wetenschappen.

Alhoewel de eerste computers in de jaren 40 van de vorige eeuw werden gebouwd is de wetenschap toch reeds in de jaren 30 pril uit de startblokken geschoten. In het begin van de 20ste eeuw waren wiskundigen zoals David Hilbert geïnteresseerd geraakt in “automatisch” bewijzen vinden. T.t.z. ze waren het beu dat je voor ieder bewijs telkens weer creatieve stappen moet doen om “het te vinden”. Zou het niet veel makkelijker zijn om eenvoudige maar strikte regels te hebben waarmee je bewijzen kon opstellen met dezelfde mechanische eenvoud als waarmee we bijvoorbeeld een staartdeling doen of een afgeleide uitrekenen? Helaas is dit onmogelijk en dat kan men formeel bewijzen. Zulke resultaten uit de berekenbaarheidstheorie waren reeds bekend vóór de eerste computers ooit gebouwd werden. Pioniers in deze deeldiscipline waren o.m. Alan Turing en Alonzo Church. Zij ontwikkelde wiskundige systemen die vandaag nog steeds de basis vormen van de meeste moderne programmeertalen.

Computerwetenschappen in de Wetenschap


Computers zijn alomtegenwoordig in de meeste beroepen en dat is natuurlijk niet anders voor wetenschappelijke beroepen. Maar daar waar vele beroepen zich kunnen beperken tot computervaardigheden hebben de meeste wetenschappers nood aan een basiskennis van de computerwetenschappen. De dingen die wetenschappers met computers moeten doen zijn immers veel meer gevorderd dan de functionaliteit die men in hogervermelde commerciële programma’s vindt.

Computerwetenschappen als Hulpmiddel

Onderzoekers bij het CERN schrijven bijvoorbeeld zélf ingewikkelde computerprogramma’s om statistische berekeningen uit te voeren over de meetwaarden die uit de verschillende detectoren van de deeltjesversneller komen. Het is met de uitkomst van zulke berekeningen dat de detectie van deeltjes (zoals recent het Higgs boson) wordt bewerkstelligd. Bij het laten botsen van deeltjes in de Large Hadron Collider is de productie van het Higgs deeltje immers zo’n zeldzaamheid en worden er bovendien zoveel andere soorten brokstukken geproduceerd, dat de onderzoekers honderden miljarden botsingen dienen te analyseren alvorens met relatieve zekerheid te kunnen zeggen dat het deeltje werd waargenomen. De enige manier waarop dat kan is door gebruik te maken van de rekenkracht van computers om statistische berekeningen uit te voeren op deze immense hoeveelheden data. Dit gebeurt niet “met Excel” of andere software die je gewoon kan kopen. Fysici schrijven zelf software die precies berekent wat zij nodig hebben. Ze gebruiken daarbij de kennis die de voorbije 60 jaar in de computerwetenschappen werd opgebouwd dus als hulpmiddel bij hun onderzoek.

Computerwetenschappen als Methodologie

Traditioneel wordt “wetenschap” bedreven als een wisselwerking tussen het opstellen van theorieën (in principe “op papier”) en het uitvoeren van experimenten (in principe “in het veld” of “in het laboratorium”) die de theorieën bevestigen dan wel verwerpen.

Door de enorme rekenkracht die er vooral de voorbije 40 jaar beschikbaar is gekomen, gaan wetenschappers meer en meer over tot het onderzoeken van wetenschappelijke problemen via computersimulaties. Zo’n computersimulatie kan aldus het experimentele gedeelte van de traditionele methodologie vervangen. Zoals reeds eerder aangehaald spreekt men in dit kader over “in silico” experimenten. Hierdoor worden de computerwetenschappen dus daadwerkelijk een deel van de onderzoeksmethodologie van andere wetenschappen.

Het komt bijvoorbeeld voor dat wetenschappers voor een bepaald probleem wél vergelijkingen kunnen opstellen maar dat die vergelijkingen ofwel te ingewikkeld zijn, ofwel te veel veranderlijken bevatten om nog analytisch oplosbaar te zijn. In dat geval worden die vergelijkingen gebruikt om een programma te schrijven en wordt dat programma gebruikt om een simulatie van de werkelijkheid te genereren. Door de uitkomst van die simulatie te vergelijken met de werkelijkheid kunnen wetenschappers de correctheid of kwaliteit van die vergelijkingen evalueren. In Japan is men bijvoorbeeld geïnteresseerd in de controle van grote massa’s mensen die aan het rennen zijn naar een schuilplaats in grote steden tijdens een aardbeving. Men heeft een vrij goed beeld over hoe individuen reageren en men kan hier relatief eenvoudig “vergelijkingen” voor opstellen. Maar men weet niet wat dat geeft als al die individuen samen zo beginnen te reageren. Daarvoor heeft men computersimulaties gebouwd van steden zoals Tokio en laat men computers 8 miljoen individuen simuleren om te zien wat het totaalbeeld wordt. Op deze manier kan men experimenteren met nieuwe infrastructuur inzake nooduitgangen, schuilplaatsen, enz.

Het uitvoeren van een simulatie (oftewel: in-silico experiment) is in de meeste takken van de wetenschap intussen een belangrijke manier geworden van “wetenschap beoefenen”. Er zijn dus drie manieren waarmee wetenschappers met elkaar vandaag interageren: theorie, experiment en simulatie. Het gebruik van computerwetenschappen als onderzoeksmethodologie om m.b.v. wiskundige modellen aan wetenschap te doen wordt in het Engels doorgaans computational science of scientific computing genoemd. In computational science gaan wetenschappers m.b.v. simulaties in silico uitvoeren omdat de echte experimenten te duur, te gevaarlijk of gewoon onmogelijk zijn met de huidige stand van de technologie. In plaats van een echt experiment uit te voeren, gaan wetenschappers simuleren wat er zou gebeuren in zo’n gevallen. Voorbeelden hiervan zijn sommige crash tests van auto’s, een simulatie van de allereerste testvluchten van nieuw ontworpen vliegtuigtypes, simulaties van raket- of satelietvluchten, enz.

Computationele Processen


Computers zijn apparaten die pas tot leven komen als men ze onder stroom zet. Vanaf dan kunnen ze vanalles “doen”. Dat gaat van simpel rekenwerk tot en met het volautomatisch besturen van vliegtuigen. De “actie” die leeft in een computer noemen we een computationeel proces. Een computationeel proces is net zoals een natuurlijk proces iets dat zich voltrekt in de tijd.

De computerwetenschappen vormen een discipline die op het kruispunt van de natuurwetenschappen en de ingenieurswetenschappen staat. Langs de ene kant is het een ingenieurswetenschap aangezien we computationele processen moeten bouwen. Zonder de computer precies uit te leggen wat hij moet doen, gebeurt er immers niets. In deze cursus zullen we minstens de helft van de tijd spenderen aan het leren bouwen van computationele processen (t.t.z. “programmeren”). Langs de andere kant is het ook een natuurwetenschap aangezien we van onze gebouwde processen bepaalde eigenschappen als een natuurfenomeen zullen bestuderen. Zo zijn bepaalde processen bijvoorbeeld inherent veel sneller dan andere. We zullen bestuderen hoe dat komt en we koppelen het begrip ervan ten slotte terug om betere processen te bouwen.

Processen en Talen

Een computer is een beetje als een viool. Ook dat is een relatief eenvoudig “apparaat” waar je ongelofelijk ingewikkelde dingen mee kan doen indien je het juist kan gebruiken. Door de juiste acties te ondernemen kan een violist de mooiste muziek uit de viool halen. Maar hiervoor dient hij wel te weten welke stappen ondernomen dienen te worden. Deze stappen staan beschreven in een partituur. Een partituur bevat “instructies” die de violist kan volgen om het proces “muziek spelen” tot leven te laten komen. De instructies op de partituur zijn neergeschreven in een vrij precieze taal die het muziekschrift heet.

We kunnen processen dus neerschrijven in talen. Dat is precies wat we in deze cursus zullen doen voor computationele processen. We zullen een taal leren (genaamd Python) waarmee we heel precies kunnen neerschrijven wat de computer moet doen. De computer zal slaafs uitvoeren wat we hebben neergeschreven en die uitvoering is dan (hopelijk) het bedoelde computationele proces.

Net zoals we een muziekstuk neergeschreven in muziekschrift een partituur noemen, zullen we een reeks computerinstructies neergeschreven in Python een programma noemen. Computationele processen ontstaan dus doordat een computer een programma uitvoert. Het programma is de tekstuele representatie van het computationele proces net zoals de partituur een tekstuele representatie is van het muziekstuk. Hieronder zien we bijvoorbeeld een programma (geschreven in Python) dat het computationele proces “gemiddeldes berekenen” beschrijft. Dit is maar om een idee te vormen; de precieze details hiervan zijn op dit moment niet belangrijk.

def average(x,y):
    return (x + y) / 2.0

We vatten dus samen: processen worden neergeschreven in een taal. Voor computationele processen spreken we over een programmeertaal. Er is een uitvoerder die het computationele proces genereert door de instructies uit de taal te volgen.

Programmeertalen

Python is beslist niet de enige programmeertaal. Er bestaan letterlijk honderden programmeertalen en daarvan zijn er enkele tientallen populair tot zeer populair geworden ook buiten de computerwetenschappen. Enkele moderne voorbeelden daarvan zijn C, C++, Pascal, Java, JavaScript, Basic, Python en Ruby.

In de berekenbaarheidstheorie kan men bewijzen dat al deze talen precies even krachtig zijn. Men noemt ze Turingcompleet, genoemd naar Alan Turing, één van de grondleggers van de computerwetenschappen. Wat bedoelen we daar precies mee? Het komt erop neer dat ieder programma dat je in één taal kan opschrijven, ook op te schrijven is in iedere andere taal. Net zoals je een boek kan vertalen van Nederlands naar Frans. Uiteraard zal het programma er in de ene taal anders uitzien dan in de andere taal. Het computationeel proces dat er door gegenereerd wordt zal echter hetzelfde zijn.

Beschouw bijvoorbeeld de opdracht om de faculteit van getallen uit te rekenen (t.t.z. bereken \(n!\) voor een gegeven \(n\)). Dat zouden we in de programmeertaal C met onderstaand programma kunnen doen. De details zijn uiteraard niet belangrijk op dit moment.

    #include <stdio.h>
     
    void main()
    {
      int c, n, fact = 1;
      printf("Enter a number:\n");
      scanf("%d", &n);
      for (c = 1; c <= n; c++)
        fact = fact * c; 
      printf("Factorial of %d = %d\n", n, fact);
    }

Hetzelfde computationele proces (t.t.z. “\(n!\) uitrekenen voor een gegeven \(n\)) maar dan neergeschreven in Python ziet er als volgt uit.

    def main():
        n    = int(input("Enter a number:\n"))
        fact = reduce(lambda a, b: a*b, range(1,n+1))
        print "Factorial of ", n, " = ",  fact

Ook hier zijn de details op dit moment niet belangrijk. We zien dat beide programma’s er op sommige punten misschien wat gelijkaardig uitzien maar op andere punten toch danig verschillen in notatie. Toch genereren ze precies hetzelfde computationele proces: beide programma’s beginnen door de gebruiker te vragen een getal in te geven, rekenen de faculteit uit van dat getal (Eng: factorial) en drukken het resultaat vervolgens af op het scherm.

Alle programmeertalen zijn dus even krachtig. Ze zijn echter niet allemaal even luxueus. Sommige talen zijn bijzonder goed geschikt om bijvoorbeeld numerieke wiskunde in te bedrijven. Andere zijn dan weer beter geschikt om artificiële intelligentie in te maken. Nog andere zijn geschikt om boordcomputers van wagens mee te programmeren. Python is een taal die zeer geschikt is voor wetenschappers en ingenieurs. Het is een taal die in 1991 is ontworpen door Guido Van Rossum in het Centrum voor Wiskunde en Informatica in Amsterdam. Intussen is Python wereldbekend en zeer populair bij exacte wetenschappers en ingenieurs. Zoek bijvoorbeeld maar eens de term “Python” op in Google om een idee te krijgen van de populariteit van Python.

Python en Jupyter notebooks

Diep binnenin werkt een computer met elektriciteit. Het is het gebruik van twee verschillende voltages en van vele minuscule schakelaartjes die “aan” of “uit” kunnen staan, dat we op conceptueel niveau kunnen denken in termen van 0 en 1, de beruchte bits (Eng: binary digits) waar iedereen al wel eens over heeft gehoord. Zo’n schakelaartje heet een “transistor” en een moderne computer bevat er letterlijk vele miljarden.

Indien we in Python aan de slag willen hebben we dus toch nog een “tolk” nodig die onze Python programma’s kan omzetten naar de “computertaal” die bestaat uit lang reeksen nullen en enen. Gelukkig bestaan er verschillende “tolken” en kan je sommigen zelf gratis downloaden van het internet. Voor deze cursus gebruiken we de vertolker die is geïntegreerd in de on-line notebooks die als cursusmateriaal dienen.

Deze notebooks zijn Jupyter notebooks. Jupyter is een non-profit, open-source project om data science en scientific computing voor verschillende programmeertalen te ondersteunen (https://jupyter.org/about). Een Jupyter notebook is samengesteld uit cellen. Sommige cellen zijn tekstcellen. Andere cellen bevatten code. Een codecel kan uitgevoerd worden omdat er een Python vertolker achter zit. Het resultaat van het uitvoeren van de code in een cel wordt vlak onder de cel weergegegeven. Zo kan je alvast zelf experimenteren met de fragmenten code die in de cursus staan. Voor de cursusnota’s hebben wij de tekstcellen geschreven en vastgeklikt zodat je ze niet per ongeluk veranderd. De codecellen hebben we de cellen meestal niet vastgeklikt, je kan de code uitvoeren door op Run te klikken in de toolbar (of met een keyboard-shortcut). Probeer gewoon eens een cijfertje in onderstaande codecel te veranderen en dan de codecel te runnen en zie wat er gebeurt.

(5+7)/2
6.0

Ook de oefeningensesssies worden als speciale notebooks beschikbaar gesteld. Je krijgt opdrachten en je kan je programma’s in code cellen tikken en uitproberen. Je kan je oplossing ook automatisch testen en je zal feedback krijgen. Als je denkt dat een oefening klaar is kan je die ‘submitten’ naar de assistenten. Zij kunnen je code op hun beurt testen om te zien of je oplossing voldoet en je eventueel ook commentaar terugsturen.

In de rest van de cursus gaan we ervan uit dat je er in bent geslaagd om toegang te krijgen tot de notebooks die wij hebben klaargezet en zetten we onze eerste stappen in Python.