Matematikk
innen datavitenskapene


Med hovedvekt på grafisk databehandling
Innledning
Med dette prosjektet vil
jeg prøve å formidle litt om sammenhengen mellom informasjonsteknologi (IKT,
det som på folkemunne går under den ganske så uriktige betegnelsen ”data”) og
forskjellige grener av matematikken. Jeg har valgt å ta for meg to temaer,
nemlig bruk av programmeringsteknikker for å ”lage oss” matematiske
hjelpemidler, og bruk av matematikk (i hovedsak lineær algebra) innen grafisk
databehandling. Jeg vil klart legge hovedvekt på den siste delen, da denne er
mest ”matematisk” i formen.
Mengden matematikk innen
disse feltene er større enn man kanskje tror, og egne erfaringer viser at det
er matematikken som skremmer de fleste datastudenter bort fra for eksempel
bildebehandling og databasestudier.
Jeg kommer bare til å
”scratch the surface” i denne oppgaven og tar for meg noen få, enkle
grunnleggende teknikker og eksempler.
Bildet på forsiden er fra
verdens første helaftens datakonstruerte tegnefilm, Toy Story, som kom fra Walt Disneys dataanimatører i 1996 (hvorvidt betegnelsen ”tegnefilm” da blir
dekkende tør jeg ikke å si noe om… Det er et ganske stort konfliktområde
akkurat rundt dette. Datagrafikerne hevder kunsten er bevart, siden det hele
tiden er mennesker som designer alt, og at datamaskinen ikke er noe annet enn
et verktøy. Fra andre hold kommer kommentarer om at kunsten blir upersonlig, og
samlebåndpreget. Debatten går, og kommer nok til å fortsette…). Det er vel
kanskje på det store lerettet at vi får de virkelig kraftige dosene med
datagrafikk.
Del 1 : Å programmere en
datamaskin til å bli et matematisk hjelpemiddel
·
Kort om
programmeringsspråket Turbo Pascal
·
Rekursjon – en
programmeringsteknikk
Del 2: Grafisk databehandling
·
Skjermen
m/koordinater
·
Scan
konvertering
·
Transformasjoner
Avslutning, kommentarer og
kilder
Vi
programmerer en funksjon
For å lage et dataprogram,
må man skrive et sett eksakte, stringente instruksjoner, som en datamaskin kan
forstå, tolke og utføre i rekkefølge. Programmeringsspråket som oftest brukes
til opplæring er nå Pascal, eller Turbo Pascal (forskjellen er at sistnevnte er
en større og mer utvidet versjon). Det
er også dette språket som brukes ved NTNU sine grunnkurs. Grunnen til at
akkurat dette språket velges, er at det er veldig ryddig satt opp, og at
teknikker som læres, forholdsvis lett kan transponeres til andre
programmeringsspråk. Jeg skal nå ta for meg noen enkle instruksjoner, slik at
man har et lite grunnlag, og dernest vise hvordan man kan løse et kjent
matematisk problem ved hjelp av dette språket. Jeg går ikke helt grundig til
verks når det gjelder korrekt ”dataskrivemåte” av disse kommandoene, men
skriver de litt mer forståelig.
Jeg vil i dette eksemplet
benytte rekursjon, en programmeringsmåte som ofte er brukt. I hovedsak går det
ut på at man løser et problem ved å løse et annet problem som er enklere, men
som likner. Ved å stadig løse enklere problem, kan man til slutt finne svaret
ut fra elementære definisjoner. Man kan definere rekursjon litt humoristisk på
denne måten:
Rekursjon
: se rekursjon.
(Ofte er denne teknikken brukt uten hell, noe Telenor kan bekrefte… En
av deres arbeidere skulle prøve ut et program han hadde skrevet. Programmet
hadde feil, og det endte med at det startet en
rekursiv sletting på serveren til Telenor, slik at hjemmesidene til en
stor mengde abonnenter forsvant.)
La oss se på et typisk,
lite Pascal-program, der vi benytter oss av rekursjon:
program
nr1;
function
mystisk (n:integer):integer;
begin{Her
begynner vi å definere funksjonen mystisk}
if n=1 then
mystisk:=1
else
mystisk:=n+mystisk (n-1);
end;{Her
er vi ferdige med å definere funksjonen mystisk}
begin{Her
begynner programmet}
writeln(mystisk(4));
end.{Her
slutter programmet}
Har man aldri sett et
dataprogram før, kan nok dette fortone seg litt kryptisk. La oss gå rolig
gjennom dette programmet og se hva som skjer. Når vi kjører i gang dette
programmet, begynner datamaskinen på toppen og utfører instruksjonene i tur og
orden.
Alt som står i
klammeparenteser er kommentarer, som datamaskinen hopper over, og som ikke blir
skrevet ut på skjermen når programmet kjøres. De er der altså bare for å hjelpe
programmereren til å holde orden.
Den første linjen, ”program nr1” , betyr bare at vi kaller
dette programmet for nr1. (Mange steder i et dataprogram må vi ha med et
semikolon for å markere slutten av linjen, men det trenger vi ikke å gå nærmere
innpå.)
I neste linje definerer vi
oss en funksjon som vi kaller mystisk.
Den kunne vi like gjerne ha kalt f,
eller gamma, eller hva som helst.
Poenget er at navnet er gjenkjennelig. Legg også merke til at funksjonen er
definert (dataterminologi : ”deklarert”) før vi starter selve programmet!!
Det som står inne i
parentesen betegner det vi vil ha inn i funksjonen vår, altså variabelen. Jeg
har valgt å kalle den n, men kunne selvfølgelig ha brukt ”x”, eller ”tall”
eller liknende. At det står ”integer” bak variabelen, betyr at vi forventer oss
at vi skal få en integer, altså et heltall inn i denne funksjonen.
Til slutt på denne linja
står det nok en gang integer, som betyr at funksjonen skal returnere en
integer.
Altså…; Vi skal sende inn
et heltall, og få et heltall som svar.
Det som nå står mellom begin og end; er det vi skal ha funksjonen til å gjøre. Det første er en
if-setning, som sjekker om en tilstand er sann, og handler deretter som en
følge av det. Vi ser at vi har to valg, enten er verdien vi får inn for n lik
en eller den er ikke lik en, og avhengig av det, gjør vi et av to valg.
Hvis variabelen har verdi
lik 1, setter vi funksjonsverdien lik 1.
Hvis variabelen er ulik 1,
setter vi funksjonsverdien lik n+mystisk(n-1). Her trengs det kanskje
forklaring. Det er nemlig her rekursjonen kommer inn. La meg forklare dette ved
å se på et eksempel!
Vi får inn n=3. Da blir i
første omgang mystisk satt til å være 3+mystisk(3-1)=3+mystisk(2). Funksjonen
kaller altså opp seg selv igjen (det er dette som er rekursivitet!), og sender
denne gangen heltallet to gjennom. Mystisk(2)=2+mystisk(2-1)=2+mystisk(1). Men
når vi sender inn tallet en, får vi fra den første definisjonen i funksjonen at
funksjonsverdien blir 1. Vi ser at vi her har en sum av funksjonsverdier, som
til sammen blir den endelige funksjonsverdien 3+2+1=6. Mystisk(3) er altså lik
6.
Videre i programmet ser vi
at det står en ny begin og end. Det som står mellom her er selve
hovedprogrammet. Det består altså bare av en instruksjon, ”writeln (mystisk(4))”. Kommandoen writeln betyr at det som står i etterfølgende parentes blir skrevet
ut på skjermen.
): Det programmet gjør, er
å beregne verdien av mystisk(4), og skriver denne verdien ut på dataskjermen.
Ved å følge samme framgangsmåte som overfor, ser vi at mystisk(4)=4+3+2+1=10.
Det eneste dette programmet vårt altså gjør, er å skrive ut tallet ”
La oss så gyve løs på det
klassiske problemet om tårna i Hanoi….
I den gamle
orienten, i den vietnamesiske byen Hanoi, døde vismannen til keiseren. For å
finne en ny vismann, lagde keiseren en oppgave, og den som klarte å løse
oppgaven, skulle få bli keiserens nye vismann. Problemet bestod av N skiver
(han spesifiserte ikke hvor mange), og tre staver, der skivene kunne ligge;
A(kilde), B(mål) og C(til overs). Skivene var av forskjellig størrelse, og
hadde hull i midten, slik at de kunne passe på stavene. På grunn av vekten
kunne en skive bare plasseres på toppen av en større skive, og ikke motsatt.
Til å begynne med, var alle skivene på stav A. Problemet gikk ut på å flytte
alle skivene fra stav A til stav B. Mange kom med sine løsninger, noen bestod
av tusenvis av flyttinger. ”Jeg skjønner ikke disse løsningene”, sa keiseren.
”Det må jo være en enkel måte å gjøre dette på!”. Og det var det selvfølgelig.
En vis buddhistisk munk kom etter hvert ned fra fjellene til keiseren og sa:
”Min sønn, dette problemet er så lett at det nesten løser seg selv!” Løsningen
munken kom med var som følger:
”Hvis det bare er en skive (N=1), så flytter vi den
fra A til B”. Alt vel så langt, men til og med landsbyenes klovn hadde gjort
den biten rett… ”Hvis det er mer enn en skive, (N>1), så gjør du følgende:
1.
Ser bort fra
den nederste skiva, og løser problemet for N-1 skiver, med den lille justering
at målet er stav C i stedet for B.
2.
Når du har gjort det, vil N-1 skiver være på stav
C, og den største vil være igjen på stav A. Så vi løser problemet for N=1 ved å
flytte den fra A til B.
3.
Nå må du bare flytte de N-1 diskene fra stav C til
stav B; det vil si, løse problemet med stav C som utgangspunkt, og stav B som
mål.
Det ble stille noen sekunder, før keiseren utbrøt:
”Vel, skal du fortelle oss løsningen eller ikke?”. Hvorpå munken smilte og bega
seg i vei til fjellet igjen.
Tydeligvis kunne ikke
keiseren tenke rekursivt. Men det er faktisk ingenting i veien med løsningen
som munken kom med. Nøkkelen til å
skjønne løsningen er å se at man kan løse problemet ved å løse tre mindre
problem! La oss nå lage en prosedyre som gjør dette for oss. (En prosedyre er
et ”delprogram” som kan utføres når som helst i et større program).
Vi betegner tower(antall, fra, til, overs) som
problemet med å flytte antall skiver
fra fra til til, og overs er den
staven som blir til overs. I keiserens tilfelle: tower(N,A,B,C). Vi kan da sette opp munkens løsning slik:
1.
tower(N-1,A,C,B)
Altså se bort fra den nederste
skiva, og løse problemet for resten.
2.
tower(1,A,B,C) Løser problemet med å flytte den største fra
A til B
3.
tower(N-
Vi ser at vi her har brukt
en rekursiv løsning:
·
Vi løser
problemet ved å løse et lignende problem.
·
De andre
problemene er enkelere, siden de involverer færre skiver.
·
Når det bare
er en skive igjen, har vi allerede løsningen for hva vi skal gjøre.
·
Etter hvert
som antall skiver minker, når vi til slutt et utgangspunkttilfelle (N=1)
Som en kuriositet tar jeg
med prosedyren som løser problemet i Turbo Pascal, og som vi ser, er det i
dette tilfellet lite kode som skal til for å løse et relativt tidkrevende
problem:
Procedure
tower(antall:integer; fra, til, overs:char);
Begin
If antall=1
Then
writeln(‘Flytt disk fra stav ‘,fra,’ til ‘, til)
Else
Begin
Tower(antall-1,fra,overs,til);
Tower(1,fra,til,overs);
Tower(antall-1,overs,til,fra);
End
End.
Til slutt kan jeg nevne
noen andre bruksområder for diskret matematikk innen programmering:
Trær, (binærtrær) brukes i
katalogisering, for for eksempel å gjenfinne data i store datalagre.
Fibonacci-sekvenser og
induksjonsbevis er også ting som egner seg godt innen programmering på grunn av
de diskrete karakteristikkene.
Her har vi altså, med en meget
begrenset kunnskap om programmering, benyttet en datamaskin til å lage en
matematisk funksjon og til å løse et praktisk problem. Det er egentlig to
hoveddeler å skille mellom når det gjelder IT og matematikk, nemlig
problemløsning av matematiske problemer ved hjelp av datamaskin, og bruk av
matematikk til å løse problemer relatert til informatikk.
Vi har sett eksempler på
den første typen, og andre eksempler kan jo være innen medisin, der man tar i
bruk datamaskiner for å løse komplekse statistiske problemer, for eksempel
relatert til å gjøre røntgen-bilder så klare som mulig.
Jeg tar nå for meg den
andre delen, og skal se på hvilken matematikk som spiller inn i grafisk
databehandling.