MATLAB Guide - Teknisk fysik i Umeå

Department of Physics
Umeå University
18 november 2014
MATLAB Guide
Marina Wallin
Martin Hansson
Per Sundholm
INNEHÅLL
1
Innehåll
1 Introduktion till MATLAB
1.1 Vad är MATLAB och varför använder vi
1.2 En första bekantskap med MATLAB . .
1.3 Hjälp . . . . . . . . . . . . . . . . . . . .
1.4 Enkla MATLAB operationer . . . . . .
1.4.1 Matematiska funktioner . . . . .
1.4.2 Vektorer . . . . . . . . . . . . . .
1.4.3 Logiska uttryck . . . . . . . . . .
1.5 Enkla script i MATLAB . . . . . . . . .
1.5.1 If, For, While . . . . . . . . . . .
1.6 Bilder i MATLAB . . . . . . . . . . . .
1.7 Regressionsanalys . . . . . . . . . . . . .
1.7.1 Linjäranpassning . . . . . . . . .
1.7.2 Konfidensintervall . . . . . . . .
1.7.3 Polynomanpassning . . . . . . .
1.7.4 Linjärisering av potensfunktion .
1.7.5 Värdering av resultat . . . . . .
det?
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
. . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
4
7
9
9
10
11
12
13
14
19
19
20
21
22
22
2 Programmering med MATLAB
2.1 Introduktion till vektorer och matriser
2.1.1 Vektorer i MATLAB . . . . . .
2.1.2 Matriser i MATLAB . . . . . .
2.1.3 Vektor- och matrisoperationer .
2.2 Mer om loopar . . . . . . . . . . . . .
2.3 Script i MATLAB . . . . . . . . . . .
2.4 Läsa in data i MATLAB . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24
24
24
27
29
32
34
35
3 Matematisk analys med MATLAB
3.1 Funktioner och derivator . . . . . . . . . . . .
3.2 Eulers metod . . . . . . . . . . . . . . . . . .
3.3 MATLAB:s ode-lösare . . . . . . . . . . . . .
3.4 Numerisk integrallösning . . . . . . . . . . . .
3.4.1 Riemannsumman . . . . . . . . . . . .
3.4.2 Trapetsregeln . . . . . . . . . . . . . .
3.4.3 Simpsons regel . . . . . . . . . . . . .
3.4.4 MATLAB:s numeriska integralräknare
3.5 Symbolhantering i MATLAB . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
38
38
40
42
43
43
44
46
47
48
4 Linjära system i MATLAB
4.1 Vektorer och matriser . . . . . . . . . . . . .
4.2 Matrisoperationer . . . . . . . . . . . . . . . .
4.2.1 Matrisaddition och subtraktion . . . .
4.2.2 Matrismultiplikation . . . . . . . . . .
4.2.3 Transponering av matriser i MATLAB
4.2.4 Matrisinvers i MATLAB . . . . . . . .
4.3 Linjär algebra i MATLAB . . . . . . . . . . .
4.3.1 Determinanter i MATLAB . . . . . .
4.3.2 Lösning av linjära system i MATLAB
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
49
49
49
50
50
51
52
52
52
53
.
.
.
.
.
.
.
.
.
.
.
.
.
.
INNEHÅLL
4.3.3
2
Egenvärden och egensystem i MATLAB . . . . . . . . . .
56
5 Statistik i MATLAB
5.1 Slumpvariabler och fördelningar i MATLAB . . . . . .
5.1.1 Slumptalsgenerering . . . . . . . . . . . . . . .
5.1.2 Slumpfördelningar . . . . . . . . . . . . . . . .
5.2 Sammanfattande statistik . . . . . . . . . . . . . . . .
5.2.1 Skattningar av väntevärde och spridningsmått
5.2.2 Statistiska plottar . . . . . . . . . . . . . . . .
5.3 Statistiska test och konfidensintervall . . . . . . . . . .
5.3.1 Normalitetstest . . . . . . . . . . . . . . . . . .
5.3.2 Test med normalfördelningsantagande . . . . .
5.3.3 Exempel . . . . . . . . . . . . . . . . . . . . . .
5.3.4 ANOVA . . . . . . . . . . . . . . . . . . . . . .
5.3.5 Oparametriska test . . . . . . . . . . . . . . . .
5.3.6 Konfidensintervall . . . . . . . . . . . . . . . .
5.4 Programspråket R . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
59
59
59
60
61
61
63
67
67
68
68
71
72
72
73
6 Klassisk mekanik med MATLAB
6.1 Newtons rörelseekvationer med numeriska metoder
6.1.1 Rörelse i en dimension . . . . . . . . . . . .
6.1.2 Rörelse i flera dimensioner . . . . . . . . . .
6.2 Verlet-integration . . . . . . . . . . . . . . . . . . .
6.2.1 Velocity-Verlet . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
74
74
74
77
78
79
A Appendix: Rapportskrivning med
A.1 Bilder i MATLAB . . . . . . . .
A.1.1 Plot-kommandot . . . . .
A.1.2 Sub-plottar . . . . . . . .
A.1.3 Symboler . . . . . . . . .
A.2 MATLAB med andra program .
A.2.1 MATLAB2tikZ . . . . . .
A.2.2 MATLAB med COMSOL
A.3 Feluppskattningar . . . . . . . .
Matlab
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
81
81
81
82
83
84
84
85
86
B Appendix: Vanliga fel
B.1 Dimensionsfel . . . . . . . . .
B.2 Indexeringsfel . . . . . . . . .
B.3 Syntaxfel . . . . . . . . . . .
B.4 Övriga fel . . . . . . . . . . .
B.5 Felsökning i MATLAB . . . .
B.5.1 Felsökning i MATLAB
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
87
87
88
89
90
91
91
C Appendix: Tips och Trix
C.1 Småtips att alltid följa . . . .
C.2 Publish . . . . . . . . . . . .
C.3 Multi-dimensionella matriser
C.4 Cell-arrayer . . . . . . . . . .
C.5 Struct . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
93
93
95
96
97
98
1
INTRODUKTION TILL MATLAB
1
3
Introduktion till MATLAB
Något man som Teknisk fysiker kommer att använda genom hela sin utbildning
och förmodligen även i det riktiga livet är MATLAB, se figur 1. MATLAB är ett
programspråk från företaget MathWorks som används av många civilingenjörer.
Den här handboken är skriven av studenter på Teknisk fysik för att hjälpa er
och göra den första bekantskapen med MATLAB enklare. För är det något
man kan vara säker på så är det att man inte kan fuska sig igenom MATLABmomenten i kurserna. Det kommer att återkomma i stort sett i varenda kurs
och en bra relation till MATLAB kommer därmed hjälpa avsevärt. MATLAB
kommer ibland vara ens värsta fiende och man kommer känna att man inte har
tid att lära sig det, då man måste räkna uppgifter och göra teoretiska labbar
hela tiden. Ett tips är att ta er tiden till att lära er MATLAB ordentligt så ni
vet när och hur man bör använda det. Ni kommer tjäna på det i längden.
Figur 1: MATLABs logga.
Det här är som sagt en handbok som är till för att hjälpa er. Vi påstår inte
på något sätt att den är världsbäst, men vi tror ändå att den är bättre än att
inte ha någonting alls. Ett tips är att samtidigt som ni läser detta dokument,
se till att testa att göra samma exempel som vi gör för bättre förståelse. Kom
ihåg att det alltid finns äldrekursare i datasalen som kan hjälpa er då ni kör
fast. Lycka till!
1.1
Vad är MATLAB och varför använder vi det?
Namnet MATLAB kommer från matrix laboratory och syftar till programmets
förmåga att hantera matriser. MATLAB är ett högnivåspråk som lämpar sig
för matematiska och tekniska beräkningar, vilket vi som civilingenjörer sysslar
en hel del med. I MATLAB kan man skriva algoritmer, beräkna matematiska
uttryck, analysera data, visualisera resultat och mycket, mycket mer.
I detta kapitel kommer vi börja med att förklara hur man kan använda
MATLAB på ett enkelt sätt för att sedan öka svårighetsgraden i senare kapitel.
1
INTRODUKTION TILL MATLAB
4
Om ni någonsin tvivlar på MATLABs styrka kan ni alltid testa att skriva
why i kommandofönstret. MATLAB kommer då ge er svar på tal.
1.2
En första bekantskap med MATLAB
När man öppnar MATLAB kommer det se ut ungefär som i figur 2. Notera
att man själv kan flytta och arrangera om som man själv vill. Det betyder att
bilden inte alltid stämmer exakt men oftast ser det ut som i figur 2. Längst
upp i fönstret finns flikar och ikoner som underlättar arbetet. Det stora fönstret
i mitten kallas för kommandofönstret, Command window, och det är där man
skriver in vad man vill göra.
Figur 2: Det här är ett exempel på hur MATLAB ser ut då man startar det.
Symbolen >> kallas för MATLAB-prompten och indikerar att man kan skriva. Om vi till exempel skriver
>> 12 + 3*(4−5) + 10/5
och trycker enter kommer MATLAB att svara
>> ans =
11
vilket är precis det vi vill. MATLAB har räknat ut vårt tal och sparat det i en
variabel som heter ans. Ibland kan det vara skönt att MATLAB skriver ut vad
den gör så man vet att allting blir rätt, men med för många utskrifter blir det
snabbt oöverskådligt. Då använder man sig av ett semikolon efter uttrycket,
>> 35*12−100;
vilket gör att ans får värdet 320 men det skrivs inte ut i kommandofönstret.
Om man skriver in
1
INTRODUKTION TILL MATLAB
5
>> a = 4;
>> b = 3;
>> a+b
i kommandofönstret kommer MATLAB se ut som i figur 3.
Figur 3: Så här kan MATLAB se ut då man utfört en del kommandon.
Som man ser har bilden förändrats genom att det tillkommit nya saker.
Längst ner till höger har vi en ruta som kallas kommandohistorik, Command
History, där man ser vilka kommandon som senast gjorts. Längst upp till höger
finns en ruta som heter arbetsyta,Workspace, där alla aktuella variabler sparas
tillsammans med deras värde. Där a för tillfället är 4, b är 3 och ans är 7. ans
är en temporär variabel, vilket betyder att variabeln bara kommer sparas tills
en ny uträkning görs och den gamla uträkningen inte längre är aktuell. Om man
skriver in
>> a−b
kommer ans byta värde till 1. Om man vill spara olika variabler en längre tid
måste man själv ge dem egna namn. Detta görs genom att skriva tex
>> sum = a+b
>> diff = a−b
vilket sparar 7 i variabeln sum och 1 i variabeln diff. Beskrivande variabelnamn
gör koden enklare att förstå för utomstående.
Om man vill spara många värden i samma variabel kan man göra det genom
att skapa en lista av tal:
>> numbers = [1 2 3 4 5]
Detta kallas även för en vektor och kommer förklaras ytterligare i avsnitt 2.1.
1
INTRODUKTION TILL MATLAB
6
Nu har vi endast skrivit kortare rader men när man gör många uträkningar
på samma gång kan det vara bra att spara det på något sätt. I MATLAB
görs detta genom att skapa en M-fil. Det kan man antingen göra genom att
klicka New → Script i huvudpanelen eller skriva edit i kommandofönstret. Då
öppnas en editor där man kan skriva sin kod. För att köra klickar man på den
gröna triangeln eller genom att skriva in m-filens namn i kommandofönstret.
Till exempel kan vi skriva
>> edit hej
då skapas en M-fil med namnet hej.m och en editor öppnas. Editorn är som ett
tomt textblad där man kan man skriva exakt samma sak som vi skrivit tidigare
men M-filen kommer sparas så att man kan fortsätta en annan dag. Det man
skrivit i kommandofönstret kommer raderas när man stänger ner MATLAB. I
figur 4 ser man hur MATLAB ser ut efter att vi skapat en M-fil. M-filen hej.m
ligger i en ruta till vänster där alla filer i samma mapp sparas. Sökvägen till den
mappen kan man se under huvudpanelen. Mer om M-filer och dess fördelar kan
man läsa i kapitel 1.5 som handlar om enkla script i MATLAB.
Figur 4: Så här kan MATLAB se ut då man skapat en m-fil och utfört en del
kommandon.
Resultaten man får från koden i sin M-fil kommer hamna i editorn. T.ex.
om man skriver
one = 1
i M-filen, kommer MATLAB svara
>> one
= 1
i editorn.
1
INTRODUKTION TILL MATLAB
1.3
7
Hjälp
Det kommer alltid finnas tillfällen då man inte är helt säker på hur man ska
skriva för att MATLAB ska göra som man vill. Det man då kan göra är att
använda sig av olika hjälpfunktioner som är inbyggda i MATLAB eller använda
internet.
Det första och kanske enklaste kommandot man ska prova är kommandot
help. Man skriver helt enkelt
>> help sqrt
och får då fram en kortare text om hur man använder kommandot sqrt, se figur
5.
Figur 5: En hjälpande text om sqrt som MATLAB returnerar efter kommandot
help sqrt.
Om man behöver mer dokumentation om kommandot eller inte är helt säker
på vad kommandot heter kan man använda sig av
>> doc plot
som öppnar ett nytt fönster med dokumentation om kommandot plot, se figur 6. Fördelen med detta sätt är att man längst upp på sidan kan söka efter
kommandon och få olika förslag om man inte är helt säker på vad man söker
efter.
1
INTRODUKTION TILL MATLAB
8
Figur 6: Ett nytt fönster i MATLAB med dokumentation om kommandot plot.
Ett tredje alternativ som man kan testa är
>> demo matlab
då får man upp ett bibliotek med kortare exempel och guider med exempelkod
till MATLAB, se figur 7.
1
INTRODUKTION TILL MATLAB
9
Figur 7: Inbyggda exempel och guider till MATLAB.
Om man inte riktigt vet vad man ska söka på är det såklart alltid enklast
att leta på internet, där Google har många svar. En otroligt bra sida är
mathworks.se, där man kan hitta väldigt mycket bra exempel och förklaringar
som MathWorks, MATLABs skapare, själva skrivit.
1.4
Enkla MATLAB operationer
Nu när vi har lärt känna MATLAB lite är det dags att gå vidare. Vi kommer
i detta avsnitt gå igenom en del enkla MATLAB operationer som kan vara bra
att ha koll på för att kunna skriva mindre program i MATLAB.
1.4.1
Matematiska funktioner
I MATLAB går det att anropa alla de matematiska funktioner som man brukar
hitta i en avancerad miniräknare. Nedan, i tabell 1, följer ett par kommandon
som är lämpliga att kunna samt deras översättning till matematisk notation.
Tabell 1: Matematiska funktioner och hur man skriver dem i MATLAB.
MATLAB
Matematisk motsvarighet
exp(x)
ex
sin(x),cos(x), tan(x)
sin(x), cos(x), tan(x)
asin(x),acos(x), atan(x) arcsin(x), arccos(x), arctan(x)
log(x), log10(x)
ln(x),√log10 (x)
sqrt(x)
x
abs(x)
|x|
Det går alltså att beräkna exempelvis
√
4 med MATLAB genom att skriva
1
INTRODUKTION TILL MATLAB
10
>> sqrt(4)
ans = 2
1.4.2
Vektorer
Begreppet vektorer kommer förklaras tydligare i senare kurser, just nu kan ni
tänka på en vektor som en lista med tal. För att skapa en vektor i MATLAB
kan man använda sig av klammeroperatorn [ ]. Med den kan man spara flera
värden till samma variabel.
numbers=[ 4 8 15 16 23 42 ]
Ett annat väldigt användbart verktyg är kolonoperatorn. Skriver man x=0:2:10
i MATLAB kommer en lista skapas som börjar på 0, har ett avstånd på 2 mellan
talen och slutar med 10.
>> x=0:2:10
x =
0
2
4
6
8
10
När man skapar vektorer är det ibland ovärderligt att snabbt kunna ta reda på
längden av den. Längden av en vektor är hur många tal som är sparad i vektorn.
Det kan man göra genom att skriva:
>> length(x)
ans =
6
Vanliga tal är i grund och botten vektorer med längden 1. Att hantera vektorerna
som skapats är enkelt. För att plocka fram till exempel det tredje elementet ur
en vektor skriver man
>> x(3)
ans =
4
och för att ändra specifika element ur en vektor skriver man
>> numbers(3)=100
numbers = 4
8
100
16
23
42
Det går att addera och subtrahera vektorer med andra vektorer med samma
längd, men det går inte att multiplicera, upphöja eller dividera. För att göra det
måste man sätta en punkt framför räknesymbolen. Genom att skriva en punkt
framför operatorn berättar man för MATLAB att man vill utföra operationen
elementvis. Om man inte skriver det kommer MATLAB utföra matrisoperationer, vilket förklaras mer ingående i avsnitt 2.1.3. Nedan följer två exempel:
>> numbers−x
ans = 4
6
>> x.*2
ans = 0
4
96
8
10
12
15
16
32
20
Som man ser har det första talet i x subtraherats från det första talet i numbers,
det andra från det andra, osv. Det går också att använda de matematiska funktioner som vi nämnt tidigare på vektorer:
1
INTRODUKTION TILL MATLAB
>> x=0:2:10
x =
0
2
4
6
>> sqrt(x)
ans =
0
1.4142
8
11
10
2.0000
2.4495
2.8284
3.1623
Här har vi alltså tagit roten ur vektorn x. Svaret har blivit avrundat vid den
fjärde decimalen. Om vi skulle vilja se fler decimaler kan vi skriva
>> format long
>> sqrt(x)
ans =
0
1.414213562373095
2.000000000000000
2.828427124746190
3.162277660168380
2.449489742783178
För att byta tillbaka skriver man format short. Det finns flera olika format
att välja mellan.
1.4.3
Logiska uttryck
I MATLAB går det att undersöka diverse logiska samband som likheter och
olikheter. I tabell 2 finns exempel på logiska operatorer som MATLAB kan
hantera.
Tabell 2: Logiska uttryck.
MATLAB
Förklaring
>, <
Större än, mindre än
>=, <=
Större/mindre än eller lika med
==
Lika med
∼=
Inte lika med
&
Logiskt och
|
Logiskt eller
Att använda logiska operatorer fungerar som att använda vilket annat räknesätt
som helst. Skillnaden är att resultatet antingen blir 0 eller 1, där 0 står för falskt
och 1 står för sant. För att exemplifiera följer några olikheter nedan:
>> 1<2
ans =
1
>> 1>2
ans =
0
>> 5<10 & 5>8
ans =
0
>> 5<10 | 5>8
ans =
1
Det tredje exemplet returnerar falskt eftersom 5 inte är både mindre än 10 och
större än 8. I det fjärde exemplet returneras sant eftersom 5 är mindre än 10.
Ett logiskt och innebär att båda villkoren måste vara uppfyllda medans logiskt
eller innebär att endast de ena villkoret måste vara uppfyllt.
Det går även att använda logiska uttryck på vektorer
>> x=0:2:10
x =
0
2
>> x<=4
ans =
1
4
1
6
8
1
10
0
0
0
1
INTRODUKTION TILL MATLAB
12
Om man använder logiska uttryck på vektorer returneras flera olika svar eftersom talen jämförs var för sig. De tre första talen i vektorn x är större eller
lika med 4 och därför returneras en etta på dessa positioner.
1.5
Enkla script i MATLAB
Vi har i kapitel 1.2 sett hur man skapar och öppnar en M-fil. Låt oss nu skrida
till verket och skriva vårt första script. Ett script är ett dokument som kör
koden rad för rad, precis på samma sätt som om vi hade skrivit rad för rad i
kommandofönstret. Men nu skriver vi klart hela koden och kör allt när vi är
färdiga. På detta sätt kan vi spara allt vi skriver i ett dokument.
Säg att vi vill beräkna arean av ett rätblock, d.v.s. en tegelstensformad
geometrisk kropp med sidolängderna 1, 2 och 3 cm. Då kommer vi ha två sidor
med arean 1·2, två med arean 1·3 och två med arean 2·3, och totalarean kommer
bli summan av dessa, alltså 22 cm2 . Denna beräkning går alldeles utmärkt att
utföra i MATLAB genom att skriva
a=1;
b=2;
c=3;
area=2*(a*b + a*c + b*c)
och spara uträkningen som ett script med namnet rArea1.m. Testkör filen genom
att sedan skriva rArea1 i MATLABs kommandoprompt.
>> rArea1
area = 22
Ett annat sätt att åstadkomma samma sak är att göra rätblocksarean till en
funktion av sidolängderna a, b och c. I MATLAB kan man skriva funktioner med
hjälp av M-filer. Variabler som skapas inuti sådana funktioner är lokala och tas
automatiskt bort när funktionen avslutas. För att definiera en funktion skapar
vi en ny M-fil med samma namn som funktionen vi tänker skriva. Det är viktigt
att ha samma namn på funktionen och M-filen annars kommer MATLAB inte
att hitta funktionen. Funktioner börjar med kommandot function som utgör
ett funktionshuvud som beskriver vilka parametrar funktionen tar och vilka
returvärden den ger tillbaka. Funktionen avslutas med kommandot end. Nedan
följer samma exempel som tidigare men den här gången är rätblocksarean en
funktion, med sidolängderna som inparametrar:
function area=rArea2(a,b,c)
area=2*(a*b + a*c + b*c);
end
Testkör funktionen genom att skriva:
>>area = rArea2(1,2,3)
area = 22
Det är viktigt att man skickar in parametrarna i rätt ordning, i detta fall har
vi a = 1, b = 2 och c = 3. Prova också att köra rArea2(1,1,1) som räknar
ut arean av en kub med sidolängden 1 cm. Fördelen med funktioner är alltså
1
INTRODUKTION TILL MATLAB
13
att man kan skicka in olika parametrar till funktionen. I det här fallet är det
sidolängderna.
Förklaringar till filen rArea2
Rad 1. Första raden i M-filen ovan deklarerar att en funktion ska skapas med
namnet rArea2. Funktionen anropas med tre argument och kommer att
returnera värdet på area. I M-filen har dessa namnet a, b och c men när
funktionen anropas från MATLAB kan dessa vara vad som helst.
Rad 2. Beräkningen av rätblocksarean utförs och resultatet tilldelas namnet area.
Det är samma area som förekom i funktionsdeklarationen på rad ett.
Detta är det sista som görs i M-filen och det är det värde som area har
just nu som kommer att returneras av funktionen. Notera att area bara
är ett namn och kan bytas ut mot vilket annat godtagbart namn som helst
bara det förekommer både i funktionsdeklarationen på rad ett och på sista
raden.
Rad 3. Kommandot end avslutar funktionen.
1.5.1
If, For, While
Ibland kan det vara väldigt användbart att kunna upprepa eller sätta något
slags villkor på när en slinga kod ska utföras. Därför finns kontrollstrukturerna
if, for och while implementerade i MATLAB. Med dessa kan man på ett
snabbt och enkelt sätt göra program som inte varit möjligt med en miniräknare.
If Om vi skriver if följt av ett logiskt uttryck, kommer koden inramad av if
och end att utföras om villkoret uppfylls. Om man önskar kan man lägga till
ett else i satsen. Då kommer det efter else att utföras om det logiska uttrycket
inte är uppfyllt. Nedan följer ett exempel:
if A==5
disp('Sant, A = 5');
else
disp('Falskt, A inte = 5');
end
Om A är lika med 5 kommer ”Sant, A = 5” att skrivas ut. Om A är något helt
annat kommer ”Falskt, A inte = 5” att skrivas ut.
For Med en for-loop kan man få kommandoraderna i slingan att upprepas
ett önskat antal gånger. Det som sker inom slingan kan varieras med hjälp av
en räknare, n i exemplet nedan, vars värde ändras en gång varje varv.
for n=1:10
n2=nˆ2;
sprintf('%d i kvadrat aer lika med %d',n,n2)
end
I denna kodsnutt är n först 1 och kvadraten räknas ut till 1. Nästa varv är n
lika med 2 och kvadraten räknas ut till 4, osv. Sista gången kommer n vara lika
med 10 och kvadraten lika med 100.
1
INTRODUKTION TILL MATLAB
14
While Om vi skriver while följt av ett logiskt uttryck, så kommer koden
inramad av while och end upprepas så länge det logiska uttrycket är uppfyllt.
Nedan följer ett exempel:
i=1;
s=0;
while(s<20)
s=s+i
i=i+1;
end
Först är s mindre än 20 och vi går in i loopen. Där ändras s till 1 och variabeln
i ökas på till 2. s ändras sedan till 3, 6, 10, 15 och slutligen 21. Loopen avslutas
då s är 21 och alltså inte längre mindre än 20, vilket sker då i är lika med 7.
1.6
Bilder i MATLAB
För att kunna analysera och presentera sitt mätdata ordentligt kan det vara
bra att visulisera det. MATLAB har ett omfattande plot-kommando till detta
ändamål som kommer att introduceras här.
Plottar och grafer är ett sätt att visualisera ett förhållandet mellan två
mängder av tal genom att sätta ut punkter i ett koordinatsystem som beskriver
detta förhållande. För att kunna plotta sina mätvärden måste vi först skapa två
listor, vi döper dem till x och y.
x=[0 1 2 3 4 5 6 7 8 9 10];
y=[1 3 5 7 9 11 13 15 17 19 21];
För att sedan plotta dessa skriver vi
plot(x,y)
och resultatet kan vi se i figur 8 nedan. För att kunna plotta två listor mot
varandra på det här sättet måste vektorerna ha samma längd.
1
INTRODUKTION TILL MATLAB
15
Figur 8: Listan y plottad mot listan x.
Som vi ser i figuren så drar MATLAB automatisk linjer mellan mätpunkterna.
För att bara plotta punkterna så skriver vi
plot(x,y,'ro')
och resultat blir enligt figur 9.
1
INTRODUKTION TILL MATLAB
16
Figur 9: Listan y plottad mot listan x som punktvärden.
Där o specificerar att mätpunkterna ska visualiseras med en ring och r
bestämmer färgen på plotten. Om man vill visualisera mätpunkterna och samtidigt ha linjer mellan dessa så skriver man den sista biten som 'ro−'. Använd
gärna hjälpfunktionen för fler alternativ om hur man kan ändra utseendet på
sin plot.
För att göra sina plottar i MATLAB ännu tydligare bör man inkludera titel
och axelnamn i sina plottar. Genom att addera raderna nedan utökar vi vårt
tidigare exempel:
plot(x,y,'ro−')
title('Titel')
xlabel('x−axelns namn')
ylabel('y−axelns namn')
Där xlabel namnger den horisontella axeln och ylabel den vertikala. Detta
ger oss figur 10 nedan.
1
INTRODUKTION TILL MATLAB
17
Figur 10: Figur med titel och namn på axlarna.
Ibland så vill man plotta två grafer samtidigt, antingen i samma fönster eller
i två separata. För att göra det behöver vi två nya listor, vi döper dessa till f
och g.
f=[0 1 2 3 4 5 6 7 8 9 10];
g=[0 3 4 5 8 11 12 13 16 19 20];
För att plotta dem i samma fönster använder vi kommandot hold on:
plot(x,y,'ro−')
hold on
plot(f,g,'gx')
title('Titel')
xlabel('x−axelns namn')
ylabel('y−axelns namn')
legend('1:a plottens namn','2:a plottens namn')
Funktionen legend() beskriver vad varje kurva representerar som man kan se
i figur 11.
1
INTRODUKTION TILL MATLAB
18
Figur 11: Figur med två olika grafer plottade i samma fönster tillsammans med
en förklarande ruta.
Avslutningsvis vill vi nu plotta de två listorna i var sitt fönster, detta görs
genom att specificera det som:
figure(1)
plot(x,y,'ro−')
title('Titel1')
xlabel('x−axelns namn')
ylabel('y−axelns namn')
figure(2)
plot(f,g,'gx')
title('Titel2')
xlabel('x−axelns namn')
ylabel('y−axelns namn')
Detta ger de två figurerna i figur 12.
1
INTRODUKTION TILL MATLAB
19
Figur 12: Två olika figurer skapade i samma MATLAB-script.
Ett avslutande tips är att MATLAB som standard sparar sina figurer som
.fig-filer vilket vissa program inte helt stödjer. Använd hellre de vanligare formaten .jpg eller .png när man sparar sina figurer.
1.7
Regressionsanalys
När man gör en statistisk undersökning, det skulle kunna vara t.ex. att man har
mätt ett tryck i en gas med avseende på temperaturen eller spänningen över ett
motstånd med avseende på strömmen, så vill man att dessa mätvärden ska följa
någon exakt matematiskt funktion så att man kan testa sina teorier. Tyvärr
är detta sällan fallet, mätvärdena hamnar oftast lite i oordning och man måste
göra ”det bästa av situationen”, eller som det också kallas regressionsanalys. Det
innebär att man använder olika matematiska hjälpmedel för att anpassa sina
mätvärden till just en matematisk funktion så att man kan testa sina teorier.
1.7.1
Linjäranpassning
En vanlig anpassning är en linjär funktion, alltså en funktion på formen y =
kx + m. Ett exempel där man använder linjär regression är Hookes lag som
beskriver kraften i en fjäder med avseende på förskjutningen från jämviktsläget
som F = Kx, där K är fjäderkonstanten och x är förskjutningen. Det finns
många sätt att göra detta i MATLAB, ett av dem är att använda funktionen
polyfit(x,y). Säg att vi har en mätserie för kraften hos en fjäder, F, mot dess
förskjutning, x. För att linjäranpassa dessa värden skriver vi
p = polyfit(x,F,1)
Vi får då tillbaka en lista innehållande värdena för linjäranpassningen. Vi återfår
dessa genom att skriva k=p(1) och m=p(2). I vårt exempel står k för fjäderkonstanten
i Hookes lag och m ligger nära 0.
För att kunna visualisera vår linjäranpassning använder vi funktionen polyval(p,x)
som skapar en lista med värden för linjäranpassningen skapad av polyfit(x,y).
Koden för detta skulle kunna se ut som nedan och det resulterar i figur 13. Notera att linjäranpassningen ibland ligger ovanför mätpunkterna och ibland under.
F=[0 0.49 0.98 1.47 1.96 2.45 2.94 3.43 3.92 4.41];
x=[0 0.016 0.037 0.066 0.092 0.116 0.143 0.154 0.176 0.188];
1
INTRODUKTION TILL MATLAB
20
p=polyfit(x,F,1);
F lfit=polyval(p,x)
plot(x,F,'rx');
hold on
plot(x,F lfit)
title('Hookes lag')
xlabel('Forskjutning')
ylabel('Kraft')
legend('Matdata','Linjaranpassning')
Figur 13: Mätdata plottat tillsammans med dess linjäranpassning.
1.7.2
Konfidensintervall
Ett konfidensintervall anger det intervall omkring medelvärdet inom vilket det
sanna värdet finns med en viss sannolikhet. De vanligaste sannolikhetsnivåerna
är 95% och 99%.
För detta ändamål måste vi först göra en linjäranpassning som i avsnitt 1.7.1
men nu skapar vi även parametern S som innehåller feluppskattningar m.m.
[p S]=polyfit(x,F,1);
För att skapa konfidensintervallet använder vi funktionen polyconf(p,x,S,alpha).
Den skapar samma lista som funktionen polyval(p,x) samt en lista med konfidensintervall för varje punkt. Vilken sannolikhetsnivå man vill ha bestäms av
1−alpha t.ex. alpha=0.05 ger en 95-procentig nivå.
Vi utvecklar exemplet i avsnitt 1.7.1 med ett 95-procentig konfidensintervall
och resultatet kan ses i figur 14.
F=[0 0.49 0.98 1.47 1.96 2.45 2.94 3.43 3.92 4.41];
1
INTRODUKTION TILL MATLAB
21
x=[0 0.016 0.037 0.066 0.092 0.116 0.143 0.154 0.176 0.188];
[p S]=polyfit(x,F,1);
[F lfit delta] = polyconf(p,x,S,0.05);
plot(x,F,'rx');
hold on
plot(x,F lfit)
plot(x,F lfit+delta,'r−−')
plot(x,F lfit−delta,'r−−')
title('Hookes lag')
xlabel('Forskjutning')
ylabel('Kraft')
legend('Matdata','Linjaranpassning','Konfidensintervall')
Figur 14: Mätdata plottat tillsammans med dess linjäranpassning och ett 95procentigt konfidensintervall.
1.7.3
Polynomanpassning
Ibland följer sina mätvärden inte någon rät linje utan de har något mer komplicerat samband. Då kan man använda sig utav ett polynom av högre ordning
t.ex. y = a1 x3 + a2 x2 + a3 x + a4 som är ett polynom av ordning 3. För att
göra en anpassning av högre ordning gör vi som i avsitt 1.7.1 med skillnaden
p=polyfit(x,y,n) där n är ordningen på polynomet som man vill anpassa med.
I vårt exempel skulle vi sätta n = 3. Det vi får tillbaka från p=polyfit(x,y,n)
är värdena på konstanterna som ska stå före varje variabel (a1 , a2 , a3 och a4
ovan). Vi hittar dessa genom att skriva:
a1=p(1)
a2=p(2)
a3=p(3)
1
INTRODUKTION TILL MATLAB
22
.
.
o.s.v.
1.7.4
Linjärisering av potensfunktion
Ibland vet man inte vilken ordning sitt polynom har och då är det användbart att
använda logaritmfunktioner. Säg att vi vill undersöka ett objekts bakomlagda
sträcka, s, under fritt fall. Vi har gjort flera mätningar av objektets position
efter olika tider t och vi vet att sträckan beskrivs som s = atb där a och b är
konstanter. Detta ger att vi kan räkna ut g, tyngdaccelerationen, ur sambandet
s = 12 g · t2 . För att lösa ut dessa konstanter börjar vi med att logaritmera
funktionerna.
s=[0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45];
t=[0.009 0.04 0.096 0.175 0.278 0.404 0.556 0.728 0.926];
lns=log(s);
lnt=log(t);
Här är funktionen log() den naturliga logaritmen. Vi får nu ett uttryck på
formen ln(s) = ln(a) + b ln(t). Nu gör vi en linjäranpassning på våra logaritmerade värden som i avsnitt 1.7.1 och får ut att våra värden blir:
ln(a) = 1.63 =⇒ a = e1.63 ≈ 5.10
b = 2.11 ≈ 2.
Vi får då alltså
s = 5.10 · t2 =⇒
1
s = 10.2 · t2
2
Det vill säga att g = 10.2 enligt detta experiment.
1.7.5
Värdering av resultat
Efter att man har gjort sina mätningar och fått sina resultat ska man bestämma
osäkerheten i resultaten. Det är viktigt för att det ger ett mått på hur korrekt
och tillförlitliga de är.
Ett vanligt osäkerhetsmått vid en linjäranpassning är R2 som visar hur bra
sin anpassningen är. Det är ett värde mellan 0 och 1 och ju närmare 1 det är
desto bättre är anpassningen. Tyvärr är detta värde lite krånligt att ta fram i
MATLAB så vi beskriver hur vi tar fram det utan att lägga för stor vikt vid att
förklara nya begrepp.
Vi fortsätter kolla på exemplet i avsnitt 1.7.1. För att få fram R2 -värdet så
måste vi beräkna s.k. residualer som sparas i variablen Fresid:
Fresid=F−F lfit;
Sedan behöver vi räkna ut summan av residualerna i kvadrat samt summan av
mätvärdena i kvadrat. Det sistnämnda gör vi med hjälp av variansen genom
kommandot var:
1
INTRODUKTION TILL MATLAB
23
SSresid = sum(Fresid.ˆ2);
SStotal = (length(F)−1)*var(F);
Vi finner sedan värdet R2 genom
r sqr = 1 − SSresid/SStotal;
I vårt exempel får vi r sqr=0.9998.
Ett annat osäkerhetsmått vid linjäranpassning är adj.R2 . Det är alltid mindre än eller lika med R2 -värdet och ger en mer pålitlig uppskattning av hur bra
linjäranpassningen är. Vi skapar den genom
rsq adj = 1 − SSresid/SStotal * (length(F)−1)/(length(F)−length(p))
Om man tyckte att denna del var lite komplicerad kan man vara lugn,
det krävs nämligen betydligt mer kött på benen för att förstå allt detta fullt
ut. Om man vill läsa mer om R2 finns det en bra Wikipedia-artikel som heter ”Coefficient of determination” som kan vara värd att kolla igenom för lite
fördjupning.
2
PROGRAMMERING MED MATLAB
2
24
Programmering med MATLAB
Att programmera i MATLAB har många fördelar. För det första är det relativt
enkelt att implementera sin kod, men det är också bra för att man kan hantera
stora mängder data då MATLABs specialitet är matriser.
När man programmerar är det viktigt, oberoende av vilket språk man sitter
i, att man förstår problemet innan man kastar sig på datorn för att skriva massa kod. Tänk efter vad det är som ska lösas och dela upp problemet i mindre
småproblem. Då kan man lösa ett delproblem i taget och kontinuerligt testa
om den delen fungerar innan man går vidare till nästa. För att testa om koden
fungerar som man har tänkt sig kan man bland annat använda sig av utskrifter, som man sen tar bort, för att se om variablerna har samma värde som
man tänkt sig. Andra bra tips är att kommentera sina koder och att indentera, det gör det lättare både för dig och eventuell hjälp att förstå koden. Fler
programmeringstips finns under appendix C Tips och Trix.
I det här kapitlet kommer vi avancera till att använda MATLAB för att
programmera. Det gör vi genom att först prata mer om vektorer, för att sedan
introducera matriser, titta på lite mer avancerade loopar och script samt hur
man läser in data till MATLAB.
2.1
Introduktion till vektorer och matriser
I introduktionskapitlet beskrevs vektorer som en lista av tal och begrepp som
klammeroperatorn och kolonoperatorn introducerades. I det här kapitlet kommer vi tydligare förklara vad en vektor och en matris är, hur man kan skapa
dem och hur de fungerar.
2.1.1
Vektorer i MATLAB
Det finns två olika sorters vektorer, radvektorer och kolumnvektorer. Väldigt
logiskt så har radvektorn sina tal sparade som en rad och kolumnvektorn som
en kolumn. Skillnaden mellan dess sätt att spara sina vektorer är viktigt i linjär
algebra för att matematiken ska stämma, mer om det kommer i kapitlet 4 Linjära
system med MATLAB. Just nu räcker det att vi vet att det finns olika sorters
vektorer.
För att skapa en radvektor, med namnet row, skriver vi:
row = [1 2 3 4 5]
row =
1
2
3
4
5
Man kan även skapa en radvektor genom att sätta ett komma mellan siffrorna:
row = [1, 2, 3, 4, 5];
För att skapa en kolumnvektor separerar man siffrorna med semikolon:
column = [1; 2; 3; 4; 5]
column =
2
PROGRAMMERING MED MATLAB
25
1
2
3
4
5
Om man råkar skapa en radvektor när man egentligen vill ha en kolumnvektor
kan det lätt åtgärdas genom att ta transponatet av radvektorn:
row = [2 4 6 8 10];
column = row'
column =
2
4
6
8
10
Transponatet av en vektor kan man ta antingen med 0 eller med kommandot
transpose.
Vektorer i MATLAB indexeras från 1, vilket betyder att om man vill ha ut
det första värdet i en vektor skriver man:
prime = [2, 3, 5, 7, 11, 13, 17, 19];
prime(1)
ans =
2
Om man vill ha ut det sista värdet i en vektor kan man använda sig utav
kommandot end:
prime(end)
ans =
19
När vi har pratat om vektorers index har vi hittills endast använt en siffra i
som representerat det i:te talet i vektorn. Men för att kunna skilja på rad- och
kolumnvektorer måste man använda sig utav två index. Ett index som motsvarar raden och ett som motsvarar kolumnen. Det tredje talet i en radvektor skrivs
alltså row(1,3) vilket betyder att vi vill ha talet som är i första raden och i
tredje kolumnen. Det tredje talet i en kolumnvektor hittas genom column(3,1).
Det kan tyckas onödigt då row(3) och column(3) kommer returnera samma
värde som row(1,3) och column(3,1) men sättet med två index är tydligare och kommer behövas då vi introducerar matriser i kapitel 2.1.2. Matriser
fungerar litegrann som 2-dimensionella vektorer. En radvektor har alltid 1 som
radindex och en kolumnvektor har alltid 1 som kolumnindex.
Kolonoperatorn, som vi tidigare i kapitel 1.4.2 använt för att skapa vektorer,
kan även användas för att ta ut värden ur en vektor:
prime(4:end)
2
PROGRAMMERING MED MATLAB
26
prime =
7
11
13
17
19
I ovanstående exempel har vi plockat ut det fjärde elementet till och med det
sista genom att använda end. Man kan även ta ut varannat tal i en vektor:
prime(1:2:end)
prime =
2
5
11
17
På liknande sätt kan man ta ut vart n:te tal genom
prime(1:n:end)
där n kan vara vilket heltal som helst. Om man vill ändra värden i en vektor
kan man också använda sig av kolonoperatorn och end:
prime(1:2:end)= 1
prime =
1
3
1
7
1
13
1
19
En vektor kan skapas på många olika sätt. I kapitel 1.4.2 har vi nämnt
klammeroperatorn och kolonoperatorn, men MATLAB har även inbyggda kommandon som är väldigt användbara när man lärt sig dem. Bland annat kan man
om man vet vilken längd man vill ha på sin vektor skapa en vektor med den
längden, antingen bestående av nollor eller ettor med hjälp av kommandona
zeros och ones:
zeros = zeros(3,1)
ans =
0
0
0
ones = ones(1,3)
ans =
1
1
1
I det här exemplet får vi en kolumnvektor zeros bestående av 3 nollor och en
radvektor ones bestående av 3 ettor. Om vet vilken storlek sin vektor kommer
att ha är det bra att allokera minne genom att först skapa en vektor med nollor
eller ettor. Storleken på vektorer har annars en tendens att växa obehindrat i
t.ex. loopar, vilket är krävande. Att ändra värdena är enklare än att låta vektorn
växa då man lägger till något.
Om man vill ha många värden i sin vektor, t.ex. om man behöver lagra en
vektor med 100 sekunder kan man använda sig av linspace:
2
PROGRAMMERING MED MATLAB
27
seconds = linspace(1,100);
Genom att använda linspace på detta sättet skapar man en vektor från 1 till
100 med 100 värden. Vill man ha fler, eller färre, värden i sin vektor kan man
ange antalet värden i sin vektor genom att lägga till en inparameter:
seconds = linspace(1,100,50);
Nu får vi en vektor från 1 till 100 med 50 värden. Detta sätt att skapa en vektor
ger ofta punkter på decimalform eftersom intervallet ska delas upp i ett givet
antal delintervall. Notera att linspace alltid skapar en radvektor så behöver
man en kolumnvektor får man ta transponatet av radvektorn som linspace
returnerar.
Om man vill skapa en vektor med slumpade tal kan man använda sig av
rand för slumpade tal mellan 0 och 1 eller randi för slumpartade heltal där
första inparametern representerar maxvärdet.
random = rand(1,4)
random =
0.6948
0.8344
0.6096
0.5747
random2 = randi(15, 4, 1)
random2 =
5
7
11
15
I det övre exemplet får vi en radvektor med 4 slumpade värden mellan 0 och
1. I det undre exemplet får vi en kolumnvektor med 5 slumpade heltal med
maxvärdet 15. För att kombinera dessa två funktioner och få slumpade tal på
decimalform som är större än ett:
random + random2'
ans =
5.6948
2.1.2
7.8344
11.6096
15.5747
Matriser i MATLAB
I inledningen av detta avsnitt nämnde vi att MATLABs styrka ligger i dess sätt
att hantera matriser och i detta delkapitel kommer vi gå igenom vad en matris
är, hur vi skapar matriser och vad vi kan göra med dem.
En matris är en samling av rad- och kolumnvektorer som bildar ett rutnät
av värden. Alla vektorer som bygger upp matrisen måste vara lika långa men
radvektorerna behöver nödvändigtvis inte vara lika långa som kolumnvektorerna. Oftast har man 2-dimensionella matriser, alltså som ett schackbräde med
värden, men man kan även ha flerdimensionella matriser men det kommer vi
inte titta närmare på här.
2
PROGRAMMERING MED MATLAB
28
För att skapa en matris gör man på samma sätt som då vi skapade rad- och
kolumnvektorer men kombinerat:
matrix = [1, 2, 3; 4, 5, 6; 7, 8, 9]
matrix =
1
4
7
2
5
8
3
6
9
Man kan även skapa en matris genom att sätta ihop radvektorer:
row1 = [10 11 12];
row2 = [20 21 22];
matrix = [row1;row2]
matrix =
10
20
11
21
12
22
Många av de sätt vi nyss lärde oss att använda för att skapa vektorer kan vi
även använda då vi vill skapa matriser, så som zeros, ones, rand och randi.
Notera att man inte kan använda linspace för att skapa matriser. Precis som
tidigare anger vi hur många rader och kolumner som vi vill ha.
zeros = zeros(2,3)
zeros =
0
0
0
0
0
0
Om man vill ha en matris med lika många rader som kolumner behöver man
endast ange ett värde:
random = rand(3)
random =
0.3017
0.0117
0.5399
0.0954
0.1465
0.6311
0.8593
0.9742
0.5708
För att ändra ett värde eller plocka ut från matrisen gör man på liknande
sätt som för vektorer. Det man måste komma ihåg är att ange både vilken rad
och kolumn som man vill använda.
matrix = [1, 2, 3; 4, 5, 6; 7, 8, 9]
matrix(2,3)
ans =
6
2
PROGRAMMERING MED MATLAB
29
Om man vill ändra alla värden på en viss rad kan man använda sig av kolonoperatorn. Uttrycket matrix(1,:) betyder första raden, alla kolumner:
matrix = [1, 2, 3; 4, 5, 6; 7, 8, 9]
matrix(1,:)
ans =
1
4
7
Man kan även använda sig av end för att ändra vissa värden i en matris.
matrix(:,2:end) = 10
ans =
1
4
7
10
10
10
10
10
10
Översta raden i ovanstående exempel betyder att på alla rader, från och med
andra kolumnen till sista, ska värdet ändras till 10.
2.1.3
Vektor- och matrisoperationer
När man arbetar med vektorer och matriser är det viktigt att hålla koll på
de vektor- och matrisoperationer som finns och skillnaden mellan dem. Som
nämndes i introduktionskapitlet, avsnitt 1.4.2, så kan man multiplicera en vektor
elementvis med sig själv men det finns även andra sätt som vi kommer gå igenom
i detta delkapitel.
Både vektorer och matriser kan hantera addition och subtraktion genom att
operationen utförs elementvis:
matrix1 = [4, 5, 32;
3, 7, 14];
matrix2 = 4*ones(2,3);
matrix1−matrix2
ans =
0
−1
1
3
28
10
matrix1 + matrix2
ans =
8
7
9
11
36
18
I det övre exemplet har vi t.ex. 32 − 4 = 28 och i det undre 32 + 4 = 36 i den
första raden och tredje kolumnen.
Man kan även multiplicera, dividera och upphöja vektorer och matriser elementvis:
2
PROGRAMMERING MED MATLAB
30
matrix1.*matrix2
ans =
16
12
20
28
128
56
matrix1./matrix2
ans =
1.0000
0.7500
1.2500
1.7500
8.0000
3.5000
matrix1.ˆ2
ans =
16
9
25
49
1024
196
Notera punkten framför operationen som symboliserar att operationen utförs
elementvis.
Det som är viktigt att tänka på när man utför dessa elementvisa operationer
är att de vektorer och matriser som används måste ha samma dimensioner, alltså
samma antal rader och kolumner, annars kommer MATLAB inte förstå vad den
ska göra och ge ett felmeddelande. När man jobbar med matriser i MATLAB
kommer man ofta få felmeddelanden, så det gäller att förstå dem när de dyker
upp. Exempel på vanliga felmeddelanden och hur man kan åtgärda dem finns i
appendix B Vanliga fel.
Addition, subtraktion, multiplikation, division och upphöjt på det sätt som
nu förklarats kallas för array-operationer och det viktiga med detta sätt är
punkten framför operationen som man vill utföra. Den betyder att operationen
kommer utföras element för element i vektorn eller matrisen och det är därför
viktigt med samma dimension.
Nu ska vi gå vidare och introducera ett nytt begrepp, matrisoperationer.
Matrisoperationerna skiljer sig från array-operationerna på det sättet att man
inte tar multiplikation och division elementvis. Istället följer man de matematiska reglerna som används i linjär algebra. I den här guiden kommer dessa regler
förklaras ytterliggare i kapitel 4 Linjära system med MATLAB. Just nu räcker
det att vi vet att det finns olika sätt att multiplicera och dividera matriser och
att resultaten blir annorlunda. För att matrismultiplicera två matriser krävs det
att den första matrisens kolumner ska vara lika många som den andra matrisens
rader. Detta kan kännas en aning rörigt så vi tittar på ett exempel:
matrix1 = [4,5;7,4;9 0]
matrix1 =
4
7
9
5
4
0
matrix2 = [3,5,11;7,9,12]
matrix2 =
2
PROGRAMMERING MED MATLAB
3
7
5
9
31
11
12
matrix1*matrix2
ans =
47
49
27
65
71
45
104
125
99
matrix2*matrix1
ans =
146
199
35
71
Notera att den nya matrisen som skapas när vi tar matrix1 matrismultiplicerat med matrix2 har fått en ny dimension med 3 rader och 3 kolumner. Tar
vi matrismultiplikationen åt andra hållet får vi en matris med 2 rader och 2
kolumner. Ordningen av multiplikationen är alltså av betydelse.
Om man vill ta samma matris multiplicerat med sig själv måste vi använda
oss av transponat-operatorn för att få dimensionerna att stämma:
matrix1 = [4,5;7,4;9 0]
matrix1 =
4
7
9
5
4
0
matrix1*matrix1'
ans =
41
48
36
48
65
63
36
63
81
Om detta var svårt att förstå så är det ingen större fara. Man kommer lära sig
mycket mer om vektorer och matriser i kursen om linjär algebra. Huvudsaken
just nu är att vetskapen om att det finns olika sätt att räkna på då det gäller
matriser finns. Det är viktigt att man kontinuerligt, då man programmerar,
kontrollerar att resultatet blev som man tänkte sig. Så länge man har koll på
det är det lugnt.
Vi kan avsluta detta delkapitlen med att reda ut några begrepp. Här har
vi pratat om vektorer och matriser men ni har säkert hört talas om arrayer,
eller så kommer ni att göra det i framtiden och då kan det vara bra att veta
skillnaden. I MATLAB är en vektor en rad eller kolumn med värden. En array är en 2-dimensionell vektor med värden som klarar array-operationer. En
matris är också en 2-dimensionell vektor men med matrisoperationer. Skillnaden mellan array-operationer och matrisoperationer är, som vi tidigare nämnt
att array-operationerna utförs elementvis medan matrisoperationerna följer de
matematiska reglerna i linjär algebra.
2
PROGRAMMERING MED MATLAB
2.2
32
Mer om loopar
Ett väldigt viktigt verktyg när man programmerar är att kunna hantera loopar
av olika slag. När man har en översiktlig koll på de olika looparna som finns och
hur de fungerar spelar det inte så stor roll i vilket programmeringsspråk som
man sitter i. Det enda som skiljer är nämligen syntaxen, alltså hur man skriver
koden, och den kan man kolla upp. Som tidigare nämnts är det viktigt att förstå
problemet innan man börjar koda och att dela upp problemet i små delproblem.
Om man gör det kommer man se att det finns väldigt många delproblem som
kan lösas med hjälp av loopar.
Vi har tidigare nämnt if, for och while vilket är de tre loopar som är mest
grundläggande. Om man lär sig att kombinera dessa på ett bra sätt kan man
lösa mycket. En loop inuti en annan loop kallas för nästlade loopar och kan vara
mycket effektivt, speciellt när man har med matriser att göra.
Ett vanligt exempel på nästlade loopar är nästlade for-loopar. På varje ställe
i matrisen area vill vi samla arean av en rektangel med sidan som radens index
och höjden som kolumnens index.
for i=1:3
for j=1:3
area(i,j) = k;
end
end
area =
1
2
3
2
4
6
3
6
9
Den yttersta for-loopen räknar upp matrisens radindex i och den inre räknar
upp matrisens kolumnindex j. Först är i lika med 1 och j lika med 1, 2 och 3
innan i ökas till 2, o.s.v.
Genom att göra en sån här loop ökar storleken på matrisen för varje varv
i loopen. Det man kan göra då för att tjäna datortid är att allokera minne för
matrisen med matris = zeros(3). Anledningen till att man skapar en matris
med rätt dimensioner men fel element och sedan definierar om elementen så att
de stämmer, är att man sparar beräkningstid. Gör man inte en matris i förväg, så
kallad förallokering, definierar MATLAB en ny matris för varje iteration, vilket
är en betydligt större ansträngning än att bara ändra ett element i matrisen.
Ha därför för vana att alltid allokera minne i förväg när det ska skapas stora
matriser eller vektorer.
Man kan också kombinera de olika looparna med varandra, t.ex. en if utanför en for. Detta kan vara väldigt effektivt som validering av data då man
bara vill utföra for-loopen om ett visst villkor är uppfyllt:
index = 0;
last = 4;
if (index > 0)
for i=index:last
vector(i) = i
end
end
2
PROGRAMMERING MED MATLAB
33
Om index är 0 som i detta fallet går vi aldrig ens in i for-loopen. Om index
hade varit 0 och vi inte hade haft if utanför for hade vi fått ett felmeddelande
som talar om att vi försöker komma åt index 0, vilket inte existerar i MATLAB:
Attempted to access vector(0); index must be a positive integer or logical.
MATLAB returnerar felmeddelanden som detta när MATLAB inte förstår vad
man menar. Då gäller det att försöka tyda utskrifterna, vilka är mer eller mindre
standardiserade. Exempel på vanliga felmeddelanden finns under appendix B
Vanliga fel. Att lägga en if-sats utanför en annan loop på detta sätt gör att
man kan kontrollera fel som annars kan uppstå, tex undvika att dela med noll,
negativa tal på längder o.s.v.
I introduktionskapitlet, avsnitt 1.5, nämnde vi if och else men det finns
även ett tredje alternativ, elseif. När man bygger en if-sats med många olika
alternativ ska man tänka på att ta det vanligaste alternativet först, eftersom
om man går in i if-satsen inte kommer gå in i elseif eller else. if kombineras
vanligtvis med de logiska operationerna som vi gick igenom i introduktionen,
se avsnitt 1.4.3. Tänk på att man även kan ha flera olika logiska uttryck i en
if. Att kombinera många olika logiska uttryck med if och elseif kan göra
programmet effektivare så det är viktigt att tänka igenom vilka alternativ man
kan tänka sig få och hur man kan kombinera dem.
weather = 1; %1 means sun, 0 means rain
temperature = 22;
if(weather>0)
if(temperature<0)
disp('Soligt, minusgrader')
elseif(temperature==0)
disp('Soligt, nollgradigt ')
elseif(temperature>0 && temperature<21)
disp('Soligt, plusgrader')
else
disp('Soligt, oever 20 grader')
end
else
disp('Regn')
end
I det här exemplet har vi förutsatt att man endast är intresserad av temperaturen om det är soligt och att det oftare är kallt än varmt. När man bygger
en if-sats behöver man inte ha med varken elseif eller else utan ibland behöver
man endast en if-rad t.ex. i början av sin kod. I nedanstående exempel vill vi
kontrollera att numret vi skickar in till while-loopen är positivt för att kunna
räkna ut fakulteten.
number = 4;
factorial = 1;
if number>0
while (number>1)
factorial= factorial*number;
number = number−1;
end
end
2
PROGRAMMERING MED MATLAB
34
En ny variant som vi inte tidigare nämnt är switch-satsen:
mynumber = 1;
switch mynumber
case −1
disp('Negativ etta');
case 0
disp('Noll');
case 1
disp('Positiv etta');
otherwise
disp('Annan siffra');
end
En switch fungerar som så att man har ett switch-uttryck som antingen är
ett nummer eller en textsträng som man sedan evaluerar mot ett case-uttryck.
När switch-uttrycket och case-uttrycket överensstämmer utförs raden under. I
ovanstående exempel är mynumber 1 och case 1 evalueras och skriver ut ”Positiv
etta”. I en switch-sats evalueras endast ett case och satsen avbryts efter blocket
är utfört. Om inget av de olika alternativen stämmer körs otherwise vilket kan
jämföras med else. Notera att otherwise är valbart precis som else.
2.3
Script i MATLAB
I introduktionen, avsnitt 1.5, nämnde vi att ett script är ett dokument i MATLAB som kör koden i filen rad för rad. Vi introducerade även funktioner med
funktionshuvud bestående av inparametrar och returvärden. I båda dessa fallen
använde vi oss av MATLABs M-filer, vilket man ska ha som vana att alltid
använda då M-filerna måste sparas för att kunna köras. Med smarta namngivningar kan man därför lätt hålla koll på sina olika koder.
Frågan är nu när man ska använda sig utav script och funktioner. Generellt
sett ska man skapa funktioner då man inser att man upprepar samma kod flera
gånger. T.ex. då man på flera ställen i sin kod räknar ut en area kan man skapa
en funktion som gör detta istället och endast anropa funktionen på flera ställen
med olika inparametrar. Tänk på att när man har funktioner så skapas lokala
variabler som inte senare kan användas. Script ska man som sagt alltid ta för
vana att använda sig av om man skriver lite längre kod som man vill spara, ska
man endast testa mindre saker kan script vara lite överdrivet.
Ett nytt begrepp som vi inte tidigare pratat om är anonyma funktioner. När
vi pratar om vanliga funktioner skapar vi funktionen i en extern M-fil och har
en annan M-fil med själva huvudprogrammet. Men ibland kan det behövas en
mindre funktion, då kan det kännas onödigt att skapa en ny fil bara för det.
Den anonyma funktionen skrivs alltså i samma M-fil som huvudprogrammet,
förslagsvis samlade på samma ställe. Ett exempel kan vara om man på många
ställen vill kvadrera tal:
sqr = @(x) x.ˆ2;
Variabeln sqr är ett funktionshandtag, @-operatorn skapar själva handtaget
och berättar att det är en anonym funktion, x:et inom parantesen beskriver
att funktionen tar ett x-värde som inparameter. Denna funktion returnerar ett
värde för varje inparameter x, så två inparametrar ger två returvärden:
2
PROGRAMMERING MED MATLAB
35
number = [2 3];
sqr(number)
sqr
= 4
9
Man kan även skapa anonyma funktioner med inga eller flera inparametrar.
constant = @() 10;
constant() + 1
ans
= 11
myfunction = @(x,y) (3*x + 12*y.ˆ2 − x*y);
myfunction(3,4)
ans
= 189
2.4
Läsa in data i MATLAB
I detta delkapitel ska vi lära oss hur man läser in data till MATLAB. Vad som
är viktigt att komma ihåg är att filen man vill läsa in ifrån måste ligga i samma
mapp som sin M-fil för att MATLAB ska hitta det. Man kan läsa in många olika
filer i MATLAB, t.ex. filer från andra program. Men hur man gör det kommer
senare i A Appendix: Rapportskrivning med MATLAB, det vi ska lära oss nu
handlar om hur man läser in data från textfiler.
Det finns många olika sätt att läsa in data i MATLAB och efter en snabb
anblick kan det verka som att alla sätt fungerar exakt likadant. Ofta kan man
läsa in en fil på många olika sätt och många har säkert sitt favoritsätt som man
alltid använder. Men självklart är inte alla sätt identiska och därför kan det vara
bra att titta på några olika så man vet vilka som finns och när dom är bra att
använda.
Vi böjar med hur man läser in data med hjälp av MATLABs grafiska interface. Det kan man göra på två olika sätt beroende på om man vill läsa in
data från en fil eller från ett urklipp. För att importera från en fil klickar man
Home → Import data, dubbelklickar på filen man vill läsa in ifrån och ett nytt
fönster öppnas, se figur 15. Här har vi läst in en textfil med endast siffror där
ena kolumnen motsvaras av längder och den andra kolumnen av skostolekar.
Man kan välja att läsa in textfilen som vektorer eller en matris. Om man läser
in som en matris kommer matrisen ha samma namn som textfilen om man inte själv ändrar det. Om man väljer att läsa in två kolumnvektorer kommer de
ha namnen VarName1 och VarName2 som initialnamn men det kan man ändra
genom at dubbelklicka på namnet och ändra till t.ex. length och size. När
man är redo att importera sin data klickar man på ikonen import längst upp
till höger.
2
PROGRAMMERING MED MATLAB
36
Figur 15: Det nya fönstret som öppnas i MATLAB då man läser in datafiler.
För att importera data från urklippet klickar man på den lilla triangeln i
Workspace och klickar sedan klistra in. För att använda denna metod krävs det
att det man har kopierat kan tydas av MATLAB. Jämför att kopiera siffersekvensen 3 4 5 med four = 4.
Om man ska ändra ofta i en textfil men man hela tiden vill läsa in datat för
att t.ex. plotta skostorleken mot längden kan det vara bra att läsa in textfilen i
ett script. Så länge filen inte byter namn kan man då köra samma program men
få olika figurer beroende på hur textfilen senast är sparad.
importdata:
Det enklaste sättet att göra detta på är att använda sig utav
importdata:
A = importdata('numbers.txt');
length=A.data(:,1);
size=A.data(:,2);
Det här sättet är ett väldigt enkelt sätt att läsa in data till en matris om man
bara har siffror och vet hur filen är uppbyggd, vilket man väldigt ofta vet då man
själv skapat textfilen. Textfilen som vi använt i detta exempel är alltså samma
som i tidigare exempel. Ibland kan man ha textfiler med en rad med text ovanför
som beskriver vad datapunkterna motsvarar. T.ex. skulle det kunna stå length
och size överst i filen. Det man kan göra då för att bara ta ut datapunkterna är
att använda sig av delimiterIn och headerlinesIn som beskriver hur datat
är separerat från varandra och på vilken rad man ska börja läsa in datat.
filename = 'numbers.txt';
delimiterIn = ' ';
headerlinesIn = 1;
A = importdata(filename,delimiterIn,headerlinesIn);
Ovanstående exempel är alltså bra om man har en rad med text ovanför sina
datapunkter.
load: Ett annat kommando som man kan använda sig av för att läsa in data
från filer till en matris är load. Utan textrad överst skriver man:
2
PROGRAMMERING MED MATLAB
37
filename = 'numbers.txt';
A = load(filename);
dmlread: Det sista sättet vi går igenom här är dmlread. Med detta kommando kan man endast läsa in filer som består utav numeriska data. En fördel med
detta sätt är att man enkelt kan bestämma på vilken rad och kolumn man vill
börja läsa in
filename = 'numbers.txt';
row = 1;
column =2;
A = dmlread(filename, row, column);
3
MATEMATISK ANALYS MED MATLAB
3
38
Matematisk analys med MATLAB
MATLAB kan vara ett användbart verktyg när man ska arbeta med analytiska
problem i en eller flera variabler. I det här avsnittet ska vi se hur MATLAB kan
hjälpa oss att derivera, integrera och lösa differentialekvationer. Utöver detta
material så finns även ett betydligt längre och mer genomgående kompendium
gjord av Institutionen för Matematik och Matematik Statistik där matematiken
är mer grundligt förklarad.
3.1
Funktioner och derivator
Vi börjar med ett exempel som tillämpar den kunskap som har behandlats i det
inledande avsnittet 1 och avsnitt 2 som rör programmering i MATLAB. Om
nedanstående exempel känns svårt bör man repetera innan man går vidare.
Låt säga att man har en funktion f (x) = ln(x). Ett bra sätt att förstå
funktionen bättre vore att rita upp den. Med MATLAB kan detta göras genom
att skriva:
x=0:0.1:3;
f=@(x) log(x);
plot(x,f(x))
xlabel('x')
ylabel('ln(x)')
Då erhålls en graf som ser ut som den i figur 16.
Figur 16: En graf av ln(x) mot x.
För att förstå funktionen ännu bättre skulle det kunna vara vettigt att rita
upp dess derivata. Ett sätt att göra detta är att i MATLAB implementera
3
MATEMATISK ANALYS MED MATLAB
39
derivatans definition
f 0 (x) = lim
h→0
f (x + h) − f (x)
.
h
(1)
Utefter definitionen i ekvation (1) skapar vi en MATLAB-funktion som numeriskt gör deriverandet åt oss:
function f prime=differential operator(f,x,h)
f prime = (f(x+h)−f(x))/h;
end
Funktionen differential operator returnerar f prime som helt enkelt är derivatan av f som är den funktionen som vi vill derivera. För att utvärdera och
rita ut derivatan, vilken står att finna i figur 17, skriver man sedan:
h=0.00001;
f prime=differential operator(f,x,h);
plot(x,f prime)
xlabel('x')
ylabel('d/dx(ln(x))')
Här har vi nöjt oss med att låta h anta värdet 0.00001 istället för att närma sig
oändligt nära noll. Det är så man hanterar gränsvärden i MATLAB. Var dock
försiktiga och använd inte allt för små tal eftersom MATLAB då kan avrunda
dem till noll. Det är speciellt vanligt med avrundningsfel då något stort tal
adderas med något litet. Man utvärderar funktionsuttryck genom att helt enkelt
skriva numeriska värden som är mycket nära gränsvärdet man söker. Att välja
ett mindre h ger ett mer korrekt värde medan ett större h ger ett mindre korrekt
värde.
3
MATEMATISK ANALYS MED MATLAB
40
Figur 17: En graf av derivatan av ln(x) mot x.
3.2
Eulers metod
För att lösa differentialekvationer kan man använda sig av Eulers metod.
Tillvägagångssättet är att man delar in intervallet man är intresserad utav i
diskreta tidssteg och sedan beräknar
yn+1 = yn + yn0 · ∆t
(2)
där ∆t är tidsstegets längd och y är funktionen vid ett visst tidssteg. För att
få ett slags intuition bakom metoden kan man visualisera att om man skulle
följa en funktions tangent en kort sträcka skulle funktionen inte hinna ändra sig
särskilt mycket gentemot tangenten. Man kan också se det som att man får ut
f genom att integrera dess derivata f 0 med en Riemannsumma. Ännu ett sätt
att se det är att man approximerar funktionen med en Taylorserie fast man har
∆t så litet att alla termer högre än ett anses vara försumbara.
Låt oss implementera denna metod i MATLAB på genom ett exempel. Säg
att vi skjuter ut en kanonkula, se figur 18, med massa m ur en kanon, på
plats r0 = (0, 0), som kan accelerera kanonkulan till en initial hastighet av
v0 = (vx0 , vy0 ). Givet att luftmotståndet går att försumma, hur långt kan då
kanonkulan flyga?
3
MATEMATISK ANALYS MED MATLAB
41
Figur 18: En schematisk bild av banan av en kanonkula som från origo skjuts
iväg med en initial hastighet v0 = (vx0 , vy0 ).
Innan vi kan använda Eulers metod måste vi såklart ställa upp ett uttryck
för problemet. Positionens derivata med avseende på tiden är hastigheten och
hastighetens derivata med avseende på tiden är accelerationen vilket ger den
kopplade differentialekvationen:
r0 = v
0
v =a
(3)
(4)
Dessutom vet vi att den enda kraften som påverkar systemet är gravitationskrafF
= (0, − mg
ten −mg, så accelerationen bör vara F = ma ⇒ a = m
m ) = (0, −g).
Följaktligen bör Eulers uppdateringsschema definierat i ekvation (2) bli
rn+1 = rn + vn · ∆t
(5)
vn+1 = vn + a · ∆t
(6)
Implementeringen av detta exempel i MATLAB resulterar i följande script:
r0=[0,0];
%Initial position
v0=[75,50]; %Initial velocity
deltat=0.001;
%Time step
g=9.82;
a=[0,−g];
%Acceleration
r(1,:)=r0;
v(1,:)=v0;
r(2,:)=r(1,:)+v(1,:)*deltat;
%Updating position
v(2,:)=v(1,:)+a*deltat;
%Updating velocity
i=2;
while(r(i,2)>=0)
%Finished when the canon ball hits the ground
r tmp=r(i,:)+v(i,:).*deltat;
%Updating position
v tmp=v(i,:)+a*deltat;
%Updating velocity
i=i+1;
r(i,:)=r tmp;
v(i,:)=v tmp;
end
plot(r(:,1),r(:,2))
3
MATEMATISK ANALYS MED MATLAB
42
Viktigt att tänka på när man implementerar sin lösning är hur man väljer
att definiera det som ska beräknas. I vårt exempel använder vi exempelvis av
två stycken tvådimensionella vektorer för hastighet respektive position, v och
r. Men det vore också möjligt att definiera systemet som fyra enkelvariabler
motsvarande x, y, v x och v y. Eller kan man hantera en vektor på formen
vec = [x,y,v x,v y]. Alternativen är många och det är därför viktigt att välja
en form som returnerar ett resultat på en form som sedan fungerar i nästa steg.
En annan, kanske ännu viktigare aspekt är att vid implementeringen se till
att ha rätt tidssteg. Med ett för litet tidssteg kommer det behövas så många
beräkningar att programmet blir hopplöst långsamt och om det är för stort
tidssteg får uträkningen dålig precision. Om tidssteget, eller intervallet som
ska beräknas, är allt för långt kommer lösningen divergera mot oändligheten.
Begreppet för detta fenomen kallas stabilitet och Eulermetodens stabilitet är
erkänt dålig. Den är faktiskt så dålig att den ofta avråds från att användas.
Anledningen till att man ofta tar upp den ändå är främst för att det är ett illustrativt exempel och att man utifrån samma princip kan skapa mycket bättre
differentialekvationslösare som exempelvis Verlet integration som används i mekanikdelen.
3.3
MATLAB:s ode-lösare
MATLAB har egna förimplementerade ordinära differentialekvationslösare. De
brukar heta något på formen odeXX där XX är två siffror som benämner vilken
Runge-Kuttametod som används. Exakt vad en Runge-Kuttametod är och hur
ode-lösaren är uppbyggt förväntas inte läsaren veta här. Allt vi för tillfället
behöver veta är att de löser system av ordinära differentialekvationer på formen
y 0 (x) = f (x, y)
(7)
I det här avsnittet kommer vi använda oss av funktionen ode45, vilken brukar
vara en stabil och bra metod att använda i de flesta lägen. Som inparameter till
funktionen ska man specificera:
ode45(f, [a, b], x0)
där f är givet av ekvation (7), vektorn [a, b] är intervallet där lösningen ska
beräknas och x0 är initialvillkoret. Om man till exempel skulle vilja finna
lösningen för differentialekvationssystemet
dA
= 2A − AB
dt
dB
AB
=
−B
dt
2
på intervallet [0, 1] med initialvillkoren A(0) = 1, B(0) = 2, skrivs detta i
MATLAB som:
f=@(t,y) [2*y(1)−y(1)*y(2);0.5*y(1)*y(2)−y(2)];
a=0;,b=1;
x0=[1,2];
Solution = ode45(f,[a,b],x0)
3
MATEMATISK ANALYS MED MATLAB
43
Som svar får vi en strukt fylld med information om lösningen till differentialekvationen som i det här fallet heter solution. Det brukar vara mest intressant
att veta vad tidsstegen och lösningen är, och för att hämta den informationen
skriver man ändelsen .x och .y för tidsstegen respektive lösningen vid tidsstegen. Skriver man Solution.x kommer man alltså få en vektor med tidsstegen,
tidstegen är inte alltid lika långa, och skriver man Solution.y får man en
matris med lösningarna, som har samma antal kolumner som längden på tidsstegsvektorn och samma antal rader som antalet rader i ekvationssystemet den
löste, i det här fallet två.
Det går även att lösa differentialekvationer av högre ordningar genom att
formulera differentialekvationen som ett system av ode:er. Som exempel kan vi
åter igen pröva att lösa exemplet i avsnitt 3.2. Genom formuleringen i ekvation
(3) och (4) kan vi i MATLAB skriva:
%y(1)=x y(2)=vx y(3)=0 y(4)=vy
%t=[0,10]
f=@(t,y) [y(2);0;y(4);−9.82];
Solution = ode45(f,[0,10],[0,75,0,50])
3.4
Numerisk integrallösning
Vissa integraler går inte att lösa analytiskt. Då är det bra att kunna lösa dem
numeriskt i t.ex. MATLAB. Nedan följer tre integralapproximationer och en
kort diskussion om precisionen hos dessa.
3.4.1
Riemannsumman
Med en Riemannsumma approximeras integralen av en kontinuerlig funktion
genom att dela upp intervallet som ska beräknas i ett antal rektanglar vars ytor
sedan summeras ihop. Antag att intervallet av intresse är [a, b], rektanglarnas
bredd är h = b−a
h och n är antalet rektanglar. Då har vi att integralen blir
Z
b
f (x)dx ≈
a
n−1
X
f (a + ih) · h.
(8)
i=0
I illustrativt syfte finns en bild av ett exempel på en Riemannintegral i figur
19. Implementeringen i MATLAB är förhållandevis enkel:
function I=riemann(fun,a,b,n)
% interval=[a,b], n=numbers of triangles
x=linspace(a,b,n+1);
h=x(2)−x(1);
%distance between two points
y=fun(x);
%function evaluation
I=0;
%initializing
for(i=1:n)
I=I+y(i)*h;
%sum of each rectangle
end
end
När man gör en numerisk metod är det mycket viktigt att tänka på dess precision. Detta kan göras med en jämförelse med en Taylorserie. Då alla steg är lika
borde första steget vara talande för hela integrationsmetoden. Vi har att första
3
MATEMATISK ANALYS MED MATLAB
44
steget är lika med hf (a) enligt ekvation (8). Om vi integrerar en Taylorserie av
f (a + h) får man
Z
h
Z
h
f (a + t)dt =
0
f (a) + f 0 (a)t + f 00 (a)
0
t2
+ ...dt =
2
h2
h3
+ f 00 (a) + ...
2
6
Jämför termerna märker vi att bara den första termen överensstämmer. Därför
kallar man Riemannsummor för en integrallösare med första ordningens precision.
f (a)h + f 0 (a)
Figur 19: En Riemannintegral där kurvan är funktionen som integreras och den
turkosa ytan är ytan som tas i beaktning i den approximativa integralen.
3.4.2
Trapetsregeln
Med trapetsregeln approximeras integralen av en kontinuerlig funktion genom
att dela upp intervallet som ska beräknas i ett antal trapetser vars ytor sedan
summeras ihop. Antag att intervallet av intresse är [a, b], trapetsernas vänster
respektive högersida har höjden f (xn ) och f (xn+1 ) där f (xn ) = a+nh. Bredden
hos trapetsen är h = b−a
h och n är antalet trapetser. Då har vi att integralen
kan approximeras som
Z
b
f (x)dx ≈
a
n−1
X
i=0
(f (xn ) + f (xi+1 )) ·
h
.
2
(9)
Integrallösningen kommer grafiskt likna den i figur 20. Implementeringen i MATLAB blir här mycket likt Riemannfallet:
3
MATEMATISK ANALYS MED MATLAB
45
function I=trapets(fun,a,b,n)
%interval=[a,b], n=number of trapezoids
x=linspace(a,b,n+1);
h=x(2)−x(1);
%distance between two points
y=fun(x);
%function evaluation
I=0;
%initializing
for i=1:n
I=I+(y(i)+y(i+1))*h/2;
end
end
%sum of each trapezoid
Återigen undersöker vi vilken precision vår metod har. Liksom tidigare är alla
steg lika, vilket borde betyda att första steget är representativt för hela integrationsmetoden. Vi har att första steget är lika med
(f (a) + f (a + h))
h2
h
h
= (f (a) + f (a) + f 0 (a)h + f 00 (a) + ...) =
2
2
2
h3
h2
+ f 00
+ ...
2
4
Jämför man detta med integralen av Taylorserien av f (a + h)
f (a)h + f 0(a)
f (a)h + f 0 (a)
h2
h3
+ f 00 (a) + ...
2
6
ser man att de två första termerna överensstämmer. Därmed är denna metod
en metod av andra ordningen.
Figur 20: En trapetsintegral där kurvan är funktionen som integreras och den
turkosa ytan är ytan som tas i beaktning i den approximativa integralen.
3
MATEMATISK ANALYS MED MATLAB
3.4.3
46
Simpsons regel
Med Simpsons regel approximeras integralen av en kontinuerlig funktion genom
att dela upp intervallet som ska beräknas i ett antal andragradspolynom vars
integraler sedan summeras ihop. Antag att intervallet av intresse är [a, b] och att
vi delar intervallet i n bitar med avstånd h ifrån varandra. Andragradspolynom
skapas för varje delinterval och är givna av
Pi (t) = 2f (xi )
t(t − xi+1/2 )
(xi+1/2 − t)(xi+1 − t)
t(xi+1 − t)
+4f (xi+1/2 )
+2f (xi+1 )
h2
h2
h2
där xi = a + hi. Polynomet ser kanske avskräckande ut men grundtanken är
helt enkelt att polynomet ska överensstämma med funktionen i början, i mitten
och i slutet av delintervallet, d.v.s. Pi (xi ) = f (xi ), Pi (xi+1/2 ) = f (xi+1/2 ),
Pi (xi+1 ) = f (xi+1 ) För att visualisera hur detta ser ut kan ni ta hjälp av figur
21. Integrerar man polynomen Pi får man att den approximativa integralen blir
Z
b
f (x)dx ≈
a
n−1
X
i=0
h
f (hi ) + 4f (hi+1/2 ) + f (hi+1 )
6
Implementeringen i MATLAB blir som följer:
function I=simpson(fun,a,b,n)
%interval=[a,b], n=number of polynomials
x=linspace(a,b,n+1);
h=x(2)−x(1);
%distance between two points
y=fun(x);
%function evaluation
yhalf=fun(x+h/2);
%function evaluation at half time step
I=0;
%initializing
for i=1:n
I=I+(y(i)+4*yhalf(i)+y(i+1))*h/6; %sum of each polynomial
end
end
Då det är relativt krävande att motivera, påstår vi utan motivering att Simpsons
regel är en metod av ordning tre. Den är med andra ord en stark och pålitlig
metod att integrera med.
3
MATEMATISK ANALYS MED MATLAB
47
Figur 21: En simpsonintegral där kurvan är funktionen som integreras och den
turkosa ytan är ytan som tas i beaktning i den approximativa integralen.
3.4.4
MATLAB:s numeriska integralräknare
I MATLAB finns det en förbyggd funktion vid namn integral(f,a,b) där
inputargumentet f är funktionen som ska integreras och a respektive b är början
och slutet för intervallet som ska integreras. Som exempel kan vi pröva att se hur
stor skillnaden är mellan våra numeriska integrallösare och MATLABs egna:
f=@(x) x.ˆ0.5 − 0.7*x.ˆ2 + 0.35.*x.ˆ3+0.3*sin(5*x)−0.01*x.ˆ5.15;
a=0; b=3; n=6;
diff1=abs(riemann(f,a,b,n)−integral(f,a,b))
diff2=abs(trapets(f,a,b,n)−integral(f,a,b))
diff3=abs(simpson(f,a,b,n)−integral(f,a,b))
diff1 =
0.6746
diff2 =
0.1217
diff3 =
0.0086
Vilket ger det förväntade svaret att skillnaden mellan MATLABs egna och våra
implementerade är minst för Simpson som är den vi vet borde ge bäst resultat.
3
MATEMATISK ANALYS MED MATLAB
3.5
48
Symbolhantering i MATLAB
MATLAB förmågan att symboliskt derivera, integrera och lösa ekvationssystem.
Detta är möjligt genom att använda sig av så kallade syms-uttryck. För att skapa
ett syms-uttryck skriver man syms och sedan den eller de variabler man vill göra
till symboler:
>> syms x
>> g=x+2*xˆ2
g =
2*xˆ2 + x
För att derivera ett syms-uttryck används funktionen diff och för att integrera
används funktionen int. Som exempel kan vi nyttja detta på vårt syms-uttryck:
g =
2*xˆ2 + x
>> diff(g)
ans =
4*x + 1
>> int(g)
ans =
(xˆ2*(4*x + 3))/6
Ytterligare ett användningsområde är att man kan konvertera syms-uttryck till
anonyma funktioner. Detta är möjligt tack vare funktionen matlabFunction.
Om vi återanvänder vårt gamla exempel får vi att:
>>g ano = matlabFunction(g)
g ano =
@(x)x+x.ˆ2.*2.0
>> g ano(2)
ans =
10
Med hjälp av syms-uttrycken kan man dessutom lösa ekvationssystem genom
funktionen solve:
>>syms x
>>eqn = sin(x) == cos(x);
>>solve(eqn, x)
ans =
pi/4
4
LINJÄRA SYSTEM I MATLAB
4
49
Linjära system i MATLAB
I det här kapitlet ska vi lära oss hur man med hjälp av MATLAB löser problem
som förekommer i linjär algebra. Här kommer MATLAB verkligen till sin rätt
då praktiskt taget alla frågeställningar till slut reduceras till matrishantering,
vilket är MATLABs specialitet.
4.1
Vektorer och matriser
I avsnitt 2.1 har vi lärt oss massa olika sätt att skapa vektorer och matriser,
repetera gärna om du känner att det behövs. När man ska lösa linjära system
i MATLAB finns det ytterligare några sätt att skapa matriser som kan vara
användbara, t.ex. diag och eye.
diag:
Vill man skapa en diagonalmatris kan man använda funkionen diag:
>> diagonal=[1,1,2,3,5,8];
>> diag(diagonal)
ans =
1
0
0
0
0
0
eye:
0
1
0
0
0
0
0
0
2
0
0
0
0
0
0
3
0
0
0
0
0
0
5
0
0
0
0
0
0
8
För att skapa en diagonalmatris bestående av bara ettor är funktionen
eye ett bra verktyg. Vill man exempelvis ha en matris med sex rader och ko-
lumner skriver man:
>> eye(6)
ans =
1
0
0
0
0
0
0
1
0
0
0
0
0
0
1
0
0
0
0
0
0
1
0
0
0
0
0
0
1
0
0
0
0
0
0
1
Notera att detta är samma sak som identitetsmatrisen.
4.2
Matrisoperationer
I den här delen ska vi utöka förmågan att hantera matriser på sätt som är vanligt
förekommande i linjär algebra. Med MATLAB går det även för stora matriser
enkelt att utföra operationer som annars hade tagit en smärre evighet att göra
för hand.
4
LINJÄRA SYSTEM I MATLAB
4.2.1
50
Matrisaddition och subtraktion
Både när man adderar och subtraherar matriser med varandra sker detta elementvis, så därför måste matriserna vara av samma dimension. Så är det både
rent matematiskt och i MATLAB:
>> A = [4, 5, 32; 3, 7, 14];
>> B = ones(2,3);
>> A−B
ans =
3
2
4
6
31
13
Om man adderar eller subtraherar matriser av olika dimensioner får man ett
felmeddelande:
>> A = [4, 5, 32; 3, 7, 14];
>> B = ones(3,2);
>> A+B
??? Error using ==> plus
Matrix dimensions must agree.
Addition eller subtraktion av en skalär är detsamma som att lägga till eller
ta bort skalärens värde på varje element i matrisen:
A = [4, 5, 32; 3, 7, 14];
>> B = 10;
>> A+B
ans =
14
13
4.2.2
15
17
42
24
Matrismultiplikation
För att matrismultiplikationen A · B ska vara definierad måste A vara en i × jmatris och B en j × k-matris. Produkten blir då sedan en i × k-matris. Skriver
man * i MATLAB efterföljer man dessa regler:
>> matrix1 = [4,5;7,4;9 0];
>> matrix2 = [3,5,11;7,9,12];
>> matrix1*matrix2
ans =
47 65 104
49 71 125
27 45 99
>> matrix2*matrix1
4
LINJÄRA SYSTEM I MATLAB
51
ans =
146 35
199 71
Uppföljs inte dessa villkor får man ett felmeddelande:
>> matrix1*matrix1 %matrix1ˆ2
??? Error using ==> mpower
Inputs must be a scalar and a square matrix.
Vill man att multiplikationen ska ske elementvis så kan man precisera detta
genom att skriva en punkt framför:
>> matrix1.*matrix1 %matrix1.ˆ2
ans =
16
49
81
4.2.3
25
16
0
Transponering av matriser i MATLAB
Det finns två sätt att transponera matriser i MATLAB, antingen med hjälp
av operatorn 0 eller med funktionen transpose (ekvivalent med .0 ). Vid första
anblick verkar de identiska:
>> RealMatrix=[2,1;3,4];
>> transpose(RealMatrix)
ans =
2
1
3
4
>> RealMatrix'
ans =
2
1
3
4
Men skillnader uppstår då man transponerar komplexa matriser. Transpose
transponerar utan att byta ut alla inlägg till deras komplexa konjugat medan 0
operatorn gör det:
ComplexMatrix =
2.0000
3.0000
1.0000 + 1.0000i
4.0000
>> transpose(ComplexMatrix)
ans =
4
LINJÄRA SYSTEM I MATLAB
2.0000
1.0000 + 1.0000i
52
3.0000
4.0000
>> ComplexMatrix'
ans =
2.0000
1.0000 − 1.0000i
4.2.4
3.0000
4.0000
Matrisinvers i MATLAB
För att få inversen av en matris används funktionen inv:
>> matrix=[1:2;3:4];
>> inv(matrix)
ans =
−2.0000
1.5000
1.0000
−0.5000
När det kommer till att lösa linjära system på formen Ax = b, där A är en
n × n-matris, x en n × 1-vektor och b en n × 1-vektor, finns det bättre metoder
än Ax = b ⇒ x = A−1 b. Att beräkna inversen är oftast mer beräkningskrävande
än exempelvis gausseliminering. Ett effektivare sätt att lösa linjära system går
att finna i avsnitt 4.3 Linjär algebra i MATLAB.
4.3
Linjär algebra i MATLAB
För att lösa fysikaliska problem och hitta tillämpningar på linjär algebra är det
mycket centralt att kunna lösa linjära system. Det här kapitlet handlar om att
lösa dessa system, hur det kan underlättas och hur man utvärderar validiteten
i svaren.
4.3.1
Determinanter i MATLAB
För att beräkna determinanten hos en kvadratisk matris använder man funktionen det i MATLAB:
>> matrix=[1:2;3:4];
>> det(matrix)
ans =
−2
En besläktad funktion till determinanten är cond. Dess inparametar är likt
det en matris medan dess returvärde är ett mått på hur singulär, d.v.s. hur
linjärt beroende, en matris är. Ju större tal desto mer linjärt beroende. Detta
kan verka märkligt då en matris ur ett strikt matematiskt synsätt aldrig kan
vara ett mellanting mellan linjärt beroende och oberoende. Antingen är någon
eller flera rader av matrisen en multipel av en annan rad eller så är den inte det.
4
LINJÄRA SYSTEM I MATLAB
53
Anledningen till att matriser tycks kunna vara det i MATLAB är att MATLAB
är ett numeriskt verktyg som approximerar och avrundar så att den absoluta
matematiska sanningen ibland försvinner. Nedan följer två exempel, det första
med ett fall som är linjärt oberoende och ett som antagligen inte är det:
>> cond(matrix)
ans =
14.9330
>> cond([1,1;1,1.00000000001])
ans =
3.9999e+011
4.3.2
Lösning av linjära system i MATLAB
En oerhört vanlig problemuppställning är att man vill finna lösningen till det
linjära systemet
Ax = b
där A är en n × n-matris och x och b är n × 1 vektorer. Att finna lösningen
till ett sådant problem är enkelt i MATLAB. Genom att använda backslashoperatorn, alternativt skriva mldivide(A,B), får man värdet på vektorn x:
>> A=[2,1;0,1];
>> b=[10;3];
>> x = A\b
x =
3.5000
3.0000
Backslash-operatorn är en intelligent funktion som genom att först analysera
matrisens egenskaper, dess dimensioner, om den är triangulär o.s.v., använder
den metod som är bäst lämpad för att lösa systemet. Hela dess relativt avancerade algoritm går att finna på MathWorks hemsida. Det är dock lätt att förväxla
backslash-operatorn med /. Skillnaden dem emellan är att / löser ut x när problemet är formulerat som xA = b, där A är fortfarande är en n×n-matris medan
x och b är 1 × n-vektorer. Vad händer då matrisen A:s determinant är noll eller nära noll? Det som händer är att MATLAB efter bästa förmåga försöker
lösa problemet ändå men utöver svaret bifogar den även ett varningsmeddelande. Nedan följer två varningsmeddelanden man säkerligen någon gång kommer
träffa på:
>> b=[1;2];
>> A=[1,1;1,1];
4
LINJÄRA SYSTEM I MATLAB
54
>> A\b
Warning: Matrix is singular to working precision.
ans =
−Inf
Inf
>> A=[10ˆ20,10ˆ19;9,1];
>> A\b
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.000000e−021.
ans =
−2.0000
20.0000
I det senare meddelandet står det RCOND = 1.000000e−021. RCOND är
ungefär som en invers, reciprocal, av den tidigare nämnda funktionen cond och
visar att en matris är linjärt beroende om returvärdet är nära noll. Funktionen
antar som mest värdet 1.
Ju större ett linjärt system blir desto mer krävande blir det för datorn att
lösa det. Den problematiken går ibland delvis att lösa med hjälp av funktionen sparse. Sparse formaterar om matrisen så att bara nollskilda matrisinlägg
sparas. Har man en matris som innehåller få inlägg med väsentlig information,
därav namnet sparse, går det att spara mycket datorkraft. Är man osäker om
matrisen har tillräckligt få nollskilda inlägg kan man använda sig av funktionen
issparse. För att använda sparse-funktionen skriver man helt enkelt:
>> hollow=[1,0,0,0,2;0,0,3,0,2;0,0,7,0,0;0,1,0,0,1;0,0,0,2,1]
hollow =
1
0
0
0
0
0
0
0
1
0
0
3
7
0
0
0
0
0
0
2
2
2
0
1
1
>> SparseHollow=sparse(hollow)
SparseHollow =
(1,1)
(4,2)
(2,3)
(3,3)
(5,4)
(1,5)
(2,5)
(4,5)
(5,5)
1
1
3
7
2
2
2
1
1
Returvärdet av sparse preciserar vilka index av matris som har något annat
värde än noll och vad värdet vid det indexet är. Syntaxen för att lösa linjära
system för sparse-matriser är exakt densamma som för vanliga matriser:
4
LINJÄRA SYSTEM I MATLAB
55
>> b=[1;6;2;0;1];
>> hollow\b
ans =
−4.1429
−2.5714
0.2857
−0.7857
2.5714
>> SparseHollow\b
ans =
−4.1429
−2.5714
0.2857
−0.7857
2.5714
Är sparse ett måste för stora matriser med få inlägg? - Kort sagt nej, men
för de läsare som är skeptiskt lagda kommer nedan en demonstration att sparseformatet visst kan vara värd att använda.
% creates a random 2000x2000 sparse matrix
A=sprand(2000,2000,0.005);
% converts the sparse matrix A to an ordinary matrix
B=full(A);
%creates a random 2000x1−vector
c=rand(2000,1);
% clocking the solution time for Ax=c
tic
disp('sparse matrix')
A\c;
toc
% clocking the solution time for Bx=c
tic
disp('regular matrix')
B\c;
toc
Exikverar man MATLAB-scriptet får man ett svar liknande detta
sparse matrix
Elapsed time is 0.165443 seconds.
regular matrix
Elapsed time is 0.601062 seconds.
Som ni ser så är det i det här fallet går det nästan fyra gånger så fort att
använda sparse-formatet som att använda sig av vanliga matriser. Noterbart
är att en matris med storleken 2000 × 2000 sällan räknas till en stor matris i
verkligheten så skillnaden blir ännu större för riktigt stora matriser.
4
LINJÄRA SYSTEM I MATLAB
4.3.3
56
Egenvärden och egensystem i MATLAB
För att finna egenvärdena till en matris använder man i MATLAB funktionen
eig. Som returvärde får man en kolumnvektor med egenvärdena:
matrix = [0 1; 1 0]
>> eig(matrix)
ans =
−1
1
Samma funktion kan utökas så att den även beräknar egenvektorer. Då är
returvärdet dels en diagonalmatris med egenvärden och dels en matris där varje
kolumn är en egenvektor
>> [eigenvectors,eigenvalues]=eig(matrix)
eigenvectors =
−0.7071
0.7071
0.7071
0.7071
eigenvalues =
−1
0
0
1
Egenvektorer och egenvärden har väldigt många tillämpningar bl.a. när man
hanterar system av linjära differentialekvationer, löser Schrödingers ekvation,
hittar stående akustiska vågor för att bara nämna några.
Nu ska vi som exempel1 göra ännu en tillämpning, nämligen en förenklad
populationsmodulering. Antag att det i en population av kaniner så överlever
hälften första året, hälften andra året och blir som mest tre år gamla. Första
året föder de inga ungar, andra året föder de 6 och tredje året föder de 8. Just
nu finns det 304 kaniner mellan 0 och 1 år, 12 mellan 1 och 2 år och 12 mellan
2 och 3 år. Det är en förenklad modell där antalet individer ständigt ökar.
• Hur kommer populationen se ut om ett år?
• Hur stor var populationen för ett år sedan?
• Hur kommer åldersfördelningen se ut när den stabiliserat sig?
Vi börjar med att skriva ned villkoren på matrisform


  
0
6 8
304
a2
0.5 0 0  12  =  b2 
0 0.5 0
12
c2
1 Ett modifierat exempel från hemsidan http://homepage.ntu.edu.tw/ jryanwang/
course/Mathematics%20for%20Management%20(undergraduate%20level)/
Applications%20in%20Ch7.pdf
4
LINJÄRA SYSTEM I MATLAB
57
där a2 , b2 , c2 är antalet kaniner för individer på sina första, andra respektive
tredje levnadsår året därpå. Första frågan reduceras alltså till ren matrismultiplikation som i MATLAB utförs som:
>> A=[0,6,8;0.5,0,0;0,0.5,0];
>> year 1=[304,12,12]';
>> year 2=A* year 1
year 2 =
168
152
6
Året efter finns det alltså 168, 152 och 6 kaniner på första, andra respektive
tredje levnadsåret. För att ta reda p hur det såg ut året innan skriver man:
   

a0
304
0
6 8
0.5 0 0  b0  =  12 
12
c0
0 0.5 0
där a0 , b0 , c0 är antalet kaniner för individer på sina första, andra respektive
tredje levnadsår året före. Här gäller det alltså att lösa ett linjärt system som i
MATLAB översätts till:
>> year 0=A\year 1
year 0 =
24
24
20
Året före fanns det 24, 24 och 20 i de respektive ålderskategorierna.
Om åldersfördelningen är stabil så kommer antalet första, andra och tredjeårskaniner an , bn , cn öka proportionerligt. Det betyder att an , bn , cn tillsammans bildar en egenvektor och att proportionalitetskonstanten är matrisens
egenvärde.

 
 
0
6 8
an
an
0.5 0 0  bn  = λ ·  bn 
0 0.5 0
cn
cn
I MATLAB är det lätt ordnat att finna egenvektorer och egenvärden med
hjälp av funktionen eig. Resultatet blir två matriser där kolumnerna i matrisen
eVector är systemets tre egenvektorer och diagonalelementen i matrisen eValue
är motsvarande egenvärden.
>> [eVector,eValue]=eig(A)
eVector =
−0.9684
−0.2421
−0.0605
0.8729
−0.4364
0.2182
−0.8729
0.4364
−0.2182
4
LINJÄRA SYSTEM I MATLAB
58
eValue =
2.0000
0
0
0
−1.0000
0
0
0
−1.0000
men som ni ser så spottar MATLAB inte ut ett entydigt svar direkt så det
kommer krävas lite resultattolkning. Eftersom vi söker efter proportioner så
vore det inte vettigt att ha negativa tal som inlägg i egenvektorn. Vid första
anblick kan det då verka hopplöst eftersom alla egenvektorer har åtminstone
något negativt inlägg men då glömmer man att ett tal gånger en egenvektor
också är en egenvektor. Alltså kan vi multiplicera med ett negativt tal och
därmed endast få positiva komponenter. För att försöka förenkla egenvektorn
är det ibland användbart att använda sig av MATLABs bråkformat genom att
skriva format rat. Gör vi det här får vi:
>> format rat
>> eVector
eVector =
−704/727
−176/727
−44/727
769/881
−769/1762
769/3524
−769/881
769/1762
−551/2525
Multiplicerar man egenvektorn i första kolumnen med -727/44 får man att
T
den egenvektorn blir (16, 4, 1) . Då har vi slutligen vårt svar. För varje tredjeårskanin går det alltså 4 andraårskaniner och 16 förstaårskaniner.
Inte övertygad? - pröva då att upprepa matrismultiplikationen väldigt många
gånger och sedan dividera med antalet tredjeårskaniner.
5
STATISTIK I MATLAB
5
59
Statistik i MATLAB
Att göra statistik för hand är sällan roligt, särskilt inte då ens stickprov består
av flera tusen observationer. I det här kapitlet ska vi lära oss hur man kan
använda MATLAB som ett verktyg för att underlätta statistiska beräkningar.
Här kommer vi främst ta upp hur man i MATLAB skapar slumptal, extraherar
information utifrån diverse statistiska fördelningar, gör statistiska test och lite
allmänt om sammanfattande statistik, d.v.s. medelvärde, varians, diagram etc.
5.1
Slumpvariabler och fördelningar i MATLAB
Massor av statistisk teori bygger på fördelningar och fördelningsantaganden.
Därför är det viktigt att bli bekant med vilka egenskaper de har och hur man
kan simulera dem. I det här avsnittet ska vi lära oss hur MATLAB kan hjälpa
oss i det avseendet.
5.1.1
Slumptalsgenerering
För att skapa slumptal i MATLAB använder man sig av en familj av funktioner
som alla slutar på -rnd, random förkortat. Framför skriver man en förkortning
av fördelningens namn. Som inparameter skriver man i regel någon fördelningsparameter. Vill man exempelvis skapa ett slumptal ifrån normalfördelningen
N (0, 1) skriver man:
>> normrnd(0,1)
ans =
−1.3077
Hade man exekverat funktionen en gång till hade svaret antagligen blivit ett
annat eftersom vi sysslar med slumptal. Som ytterligare inparameter kan man
precisera hur många slumptal man vill ha och på vilken form de ska vara. Vill
man ha en 1×5-vektor vars inlägg är slumptal ifrån samma fördelning som ovan
skriver man:
>> normrnd(0,1,1,5)
ans =
−0.0146
0.2171
0.1802
−0.5205
−0.2396
Det här var bara en av många funktioner som skapar slumptal men alla fungerar
på mer eller mindre liknande sätt som exemplet ovan. Ett axplock av de mest
förekommande slumptalen finner ni i tabell 3.
5
STATISTIK I MATLAB
60
Tabell 3: En tabell på förkortningar på slumpfördelningsfunktioner i MATLAB
Fördelning
pdf
cdf
slumptal
Binomial
binopdf
binocdf
binornd
χ2
chi2pdf
chi2cdf
chi2rnd
Exponential
exppdf
expcdf
exprnd
F
fpdf
fcdf
frnd
Normal
normpdf
normcdf
normrnd
Poisson
poisspdf poisscdf poissrnd
Student t
tpdf
tcdf
trnd
Uniform
unifpdf
unifcdf
unifrnd
En viktig sak att ha i åtanke är att slumptalen vi skapar inte är helt
slumpmässiga utan är så kallade pseudoslumptal. De ser slumpmässiga ut och
har samma egenskaper som verkliga slumptal men det går, om man vill, att
upprepa dem. Talen man skapar följer en förutbestämd sekvens och med hjälp
av kommandot randn går det att bestämma var någonstans i sekvensen man
vill börja. Platsen i sekvensen brukar på engelska kallas för random seed. Nedan
följer ett exempel hur man genom att använda slumpfröet kan återskapa samma
händelse:
>> randn('seed',1)
>> normrnd(0,1,1,5)
ans =
0.9794
−0.2656
−0.5484
−0.0963
−1.3807
−0.5484
−0.0963
−1.3807
>> randn('seed',1)
>> normrnd(0,1,1,5)
ans =
0.9794
−0.2656
Hade man inte angett slumpfröet innan hade raden normrnd(0,1,1,5) returnerat olika värden.
5.1.2
Slumpfördelningar
För att se vilket värde som sannolikhetsfördelningen hos en fördelning antar
använder man sig av en familj av funktioner som i likhet med de som skapar
slumptal börjar med en förkortad version av fördelningens namn men slutar med
sufixet -pdf. Pdf står för engelskans probability density function. Utöver att skriva var i x-led man vill veta sannolikhetsdensiteten måste man i inparametern,
som hos rnd-funktionerna, precisera värdena på parametrarna i fördelningen.
Om vi exempelvis skulle vilja veta sannolikhetsdensiteten i punkten X = 3 om
X är Poissonfördelad enligt X ∼ P o(λ = 2) skriver vi:
>> poisspdf(3,2)
ans =
5
STATISTIK I MATLAB
61
0.1804
Analogt med pdf:en finns det funktioner som med suffixet -cdf, cumulative density function, ger den kumulativa sannolikhetsfördelningen hos en slumpfördelning.
Återanvänder vi samma exempel som tidigare kan vi antingen utnyttja att
pdf:en är diskret eller bara använda MATLABs inbyggda cdf-funktion:
>> poisspdf(0,2)+poisspdf(1,2)+poisspdf(2,2)+poisspdf(3,2)
ans =
0.8571
>> poisscdf(3,2)
ans =
0.8571
Som ni säkert märker så finns det ett stort släktskap mellan funktionerna
och hur de fungerar. I tabell 3 finns namnen på flera statistiska fördelningar som
kan vara bra att kunna namnet på ifall ni behöver göra något av det vi gjort
ovan.
5.2
Sammanfattande statistik
För att kunna analysera och tolka data måste man först skapa sig en överblick,
d.v.s. hitta medelvärde, spridningsmått och diagram av olika slag. I MATLAB
finns en rad olika funktioner för att göra just detta som vi nu ska bli mer bekanta
med.
5.2.1
Skattningar av väntevärde och spridningsmått
Till att börja med läser vi in det data som vi vill analysera. Se avsnitt 2.4 om ni
behöver repetera hur man läser in filer. Datat vi kommer analysera är en vektor
med 60 årsmedeltemperaturer i den amerikanska staden New Haven i Fahrenheit
mellan åren 1912-1971. För att läsa in datat använder vi importdata:
>> temperature=importdata('NHtemp.txt');
För att beräkna medelvärdet använder man sig av funktionen mean och använder
datat som inparameter:
>> mean(temperature)
ans =
51.1533
Medelvärdet av medelårstemperaturerna är alltså 51.1533 grader Fahrenheit
eller runt 10.5 ◦ C. Med funktionen median kan vi även hitta medianen av vårt
data:
>> median(temperature)
5
STATISTIK I MATLAB
62
ans =
51.1000
Ett väldigt enkelt spridningsmått som är bra att använda för att få en intuitiv
överblick av datat är spannet mellan det lägsta och högsta värdet. Det får man
genom att använda kommandot range:
>> range(temperature)
ans =
6.7000
För statistiska beräkningar är dock variansen betydligt mer användbar. Den
beräknas med hjälp av funktionen var:
>> var(temperature)
ans =
1.6012
För att beräkna standardavvikelsen kan man istället för att dra roten ur variansen skriva std som står för standard deviation:
>> std(temperature)
ans =
1.2654
Alla räkneoperationer vi gjort ovan går även att göra på matriser. Då ser MATLAB varje kolumn i matrisen som en separat serie mätvärden:
>> A = [1 2 3; 4 5 6; 7 8 9]
A =
1
2
4
5
7
8
>> range(A)
3
6
9
ans =
6
6
6
5
6
>> mean(A)
ans =
4
Ofta arbetar man med ofullständigt data, vissa mätpunkter kanske råkar glömmas
bort eller så har de antagit så konstiga värden att de måste försummas. Då brukar man i MATLAB ersätta de inläggen med NaN, not a number. Problematiken
5
STATISTIK I MATLAB
63
som då uppstår är att man då inte får väldefinierade svar ifall man beräknar
saker som medelvärde eller varians. Om man exempelvis byter ut några inlägg
i matrisen A från kodexemplet ovan med några NaN får man:
>> A(2,1:2:3)=[NaN,NaN]
A =
NaN
4
7
2
5
8
NaN
6
9
5
NaN
>> mean(A)
ans =
NaN
Till vår räddning kommer funktionerna nanmean, nanmedian, nanstd och nanvar
som utelämnar NaN:arna och sedan beräknar respektive kvantitet.
>> nanmean(A)
ans =
5.5000
5.2.2
5.0000
7.5000
Statistiska plottar
Ett mycket vanligt, enkelt och bra sätt att visualisera statistisk data är att
göra ett histogram. I det ändamålet används funktionen hist. Om vi återigen
använder oss av temperaturdatat i avsnitt 5.2.1 och skriver hist(temperature,5)
får vi en bild enligt figur 22, där siffran 5 representerar antalet staplar i den högra
bilden.:
5
STATISTIK I MATLAB
64
18
35
16
30
14
25
12
10
20
8
15
6
10
4
5
2
0
46
48
50
52
54
0
46
48
50
52
54
Figur 22: Till vänster: automatiskt skapat histogram d.v.s. det histogram som
erhålls av hist(temperature). Till höger: histogram där man specificerat fem
staplar genom att skriva hist(temperature,5).
Utöver att ge en överblick ger histogrammet även en hint om vilken fördelning
stickprovet har. Är histogrammet klockformat så är datat normalfördelat. Är
man osäker på om formen på histogrammet är klockformat eller inte går det
med funktionen histfit till och med att få en normalfördelningskurva utritad
i histogrammet, se figur 23.
5
STATISTIK I MATLAB
65
20
15
10
5
0
47
48
49
50
51
52
53
54
55
Figur 23: Histogram med utritad normalfördelning
Det finns dock några svagheter med histogram. För det första är de mycket
godtyckliga då antalet staplar och deras indelningar definieras av histogrammets
skapare och för det andra går det bara att påvisa normalfördelning. En plot
som är bättre på båda sakerna är den så kallade kvantil-kvantilplotten. Kvantilkvantilplotten, som namnet antyder, går ut på att man ritar ut kvantilerna hos
två stickprov på x- respektive y-axeln och ser om de följer en rät linje. Om de
gör det är formen d.v.s. fördelningen hos de båda fördelningarna lika oavsett om
stickproven har olika storlek, skalor eller är förskjutna åt något håll. Eftersom
vi har med slumptal att göra så kommer vi naturligtvis aldrig få att punkterna precis bildar en rät linje men så länge punkterna är sånär linjära bedöms
fördelningarna som likartade. För att göra en kvantil-kvantilplot använder man
funktionen qqplot. Om man inte specificerar två stickprov kommer MATLAB
göra en kvantil-kvantilplot mot normalfördelningen. För att se hur en kvantilkvantilplot ser ut då fördelningsantagandet faktiskt stämmer kan vi pröva att
stoppa in normalfördelat data i qqplot-funktionen, resultatet illustreras i figur
24.
>> qqplot(normrnd(10,4,1,100)) %my=10 standard deviation=4
%system size=1x100−vektor
5
STATISTIK I MATLAB
66
QQ Plot of Sample Data versus Standard Normal
Quantiles of Input Sample
20
15
10
5
0
−3
−2
−1
0
1
2
3
Standard Normal Quantiles
Figur 24: Kvantil-kvantilplot av två stickprov tillhörande normalfördelningarna
X ∼ N (0, 1) och Y ∼ N (10, 2)
.
Omvänt kan vi pröva att undersöka två stickprov som inte är lika fördelade,
till exempel exponential och student t fördelade observationer:
>> qqplot(trnd(5,1,100),exprnd(5,1,100))
%Student t: degree of freedom=5, system size=1x100−vektor
%Exponential: lambda=5, system size=1x100−vektor
Resultatet visar tydligt att stickproven inte är lika fördelade se figur 25.
5
STATISTIK I MATLAB
67
Y Quantiles
20
10
0
−10
−4
−3
−2
−1
0
1
2
3
4
X Quantiles
Figur 25: Kvantil-kvantilplot av ett stickprov tillhörande exponentialfördelningen X ∼ exp(λ = 5) och ett tillhörande student t fördelningen
Y ∼ t5 .
5.3
Statistiska test och konfidensintervall
En central del av statistiken är tester och konfidensintervall. De allra flesta
statistiska analyser mynnar tillslut ut i testandet av någon sorts nollhypotes.
Här hade vi tänkt visa hur några endimensionella tester går till i MATLAB.
5.3.1
Normalitetstest
Väldigt många statistiska test förutsätter att stickprovet vi testar är normalfördelat.
Därför är det viktigt att kunna se om det antagandet är troligt. Ett sätt att
göra det är med hjälp av statistiska normalitetstest. Dock är det viktigt att
förstå testens natur innan man använder dem. I testen är nollhypotesen H0 att
stickprovet är normalfördelat och den alternativa hypotesen H1 är att stickprovet inte är det. Om man kan förkasta H0 betyder det alltså att man motbevisat
att datat är normalfördelat. Kan H0 inte motbevisas fortsätter den att gälla
och det betyder att stickprovet kan vara normalfördelat. Det betyder dock inte
att H0 är bevisad så var försiktig och gör alltid ett histogram eller en kvantilkvantilplot för att se en tendens till normalfördelning innan testet utförs. Det är
exempelvis mycket svårt att med ett statistiskt test motbevisa normalitet när
stickprovet är litet. Två användbara normalitetstest i MATLAB är kstest och
jbtest.
kstest: Kstest står för Kolmogorov-Smirnov test och testar om ett stickprov är standard-normalfördelat (d.v.s. ∼ N (0, 1)).
5
STATISTIK I MATLAB
68
jbtest: Jbtest står för Jarque-Bera test och testar om stickprovet antar
någon form av normalfördelning.
Båda funktionerna tar stickprovet som inparameter och returnerar antingen 0 om normalfördelning inte kan motsägas, eller 1 om normalfördelning kan
förkastas. Preciserar man att man vill ha två returvärden får man utöver det
också testets p-värde.
5.3.2
Test med normalfördelningsantagande
Det första som bör göras innan alla sorter av parametriskt test är att testa
fördelningsantagandet. För att se om datat är normalfördelat är det viktigt att
visualisera datat man har. Det görs lätt med ett histogram eller en kvantilkvantilplot, se del 5.2.2. Ofta är det tillräckligt men för att vara säker kan man
därefter göra ett normalitetstest. Efter det kan man börja testa sina nollhypoteser. Tre verktyg att göra detta med är funktionerna ttest, ttest2 och
ztest.
ttest: Funktionen ttest utför ett vanligt t-test på stickprovet. Specificerar man
inte annat kommer MATLAB testa H0 : µ = 0. Har man två parvis observerade
stickprov som input kommer MATLAB testa H0 : µ1 − µ2 = 0. Här antar man
att skillnaden mellan de två stickproven är normalfördelad och antar inget om
hurvida de två stickproven är normalfördelade eller ens ifrån samma fördelning.
ttest2: Med ttest2 testar man för att undersöka om två normalfördelade stickprov har samma väntevärde, d.v.s. H0 : µ1 − µ2 = 0. Som default-läge kommer
MATLAB anta att normalfördelningarna har samma (okända) varians. Vill man
testa utan det antagandet skriver man 'unequal' som inparameter.
ztest: Är variansen på stickprovets normalfördelningen känd, eller att stickprovet är så stort (> 30) att centrala gränsvärdessatsen kan användas, är det
lämpligt att använda att använda z-testet. Dess inparameterar är stickprovet,
väntevärdet man vill testa och variansen stickprovet har.
Gemensamt för alla tre test ovan är att man kan skriva
[H,P,CI,stats]=test(...). Då får man utöver ett eventuellt förkastande av
nollhypotesen, p-värdet, ett konfidensintervall och en strukt med värdet på teststatistiken, antalet frihetsgrader och standardavvikelsen.
5.3.3
Exempel
Det har gjorts ett experiment där man skulle testa om det spelar någon roll
vilken hand man använder när man utför enklare uppgifter. 25 högerhänta studenter fick i uppgift att vira en viss mängd snöre runt ett rör som var fastmonterat i väggen. Första försöket skulle de bara använda högerhanden och i
det andra försöket bara vänstra. Vår uppgift är att se om det är någon signifikant skillnad mellan vilken hand som används, det vill säga testa nollhypotesen
H0 : µh − µv = 0. I det här exemplet är datat redan inläst som en matris
där första kolumnen är tiden det tog att bli klar med högerhanden och andra
kolumnen är tiden det tog för vänsterhanden.
5
STATISTIK I MATLAB
69
>> disp(experiment)
113
137
105
105
130
133
101
108
138
115
118
170
87
103
116
145
75
78
96
107
122
84
103
148
116
147
107
87
118
166
103
146
111
123
104
135
111
112
89
93
78
76
100
116
89
78
85
101
88
123
Det första vi gör är att se om stickprovet är normalfördelat så vi kan använda oss
av ett parat t-test. Till att börja med så gör vi en kvantil-kvantilplot, resultatet
ser vi i figur 26.
>> qqplot(experiment)
5
STATISTIK I MATLAB
70
QQ Plot of Sample Data versus Standard Normal
180
Quantiles of Input Sample
160
140
120
100
80
60
40
−2.5 −2 −1.5 −1 −0.5
0
0.5
1
1.5
2
2.5
Standard Normal Quantiles
Figur 26: Kvantil-kvantilplot mot standard-normalfördelning. Grön är tiden när
vänsterhanden används och blå är tiden när högerhanden används.
Både tiden för vänster- och högerhanden verkar normalfördelade. För att
vara riktigt säkra gör vi även ett normalitetstest:
>> jbtest(experiment(:,1))
ans =
0
>> jbtest(experiment(:,2))
ans =
0
Nollhypotesen att datat är normalfördelat går alltså inte förkasta. Nu när vi är
relativt säkra på att normalfördelning gäller kan vi göra ett parat t-test. Vi antar
att båda stickproven har samma varians. Utöver att veta utgången H av testet
vill vi också veta p-värdet P och konfidensintervallet CI samt vad medelvärdet
av tidsskillnaden mellan väster- och högerhand är.
>> [H,P,CI]=ttest2(experiment(:,1),experiment(:,2))
H =
1
5
STATISTIK I MATLAB
71
P =
0.0398
CI =
−25.9904
−0.6496
>> mean(experiment(:,1)−experiment(:,2))
ans =
−13.3200
Vi kan alltså på grund av det låga p-värdet (p < 0, 05) förkasta nollhypotesen
att det inte skulle vara någon skillnad vilken hand man använder.
5.3.4
ANOVA
Har man fler än två stickprov och vill testa om alla har samma väntevärde kan
man använda sig av ANOVA. ANOVA står för analysis of variance och är en
statistisk metod för att analysera de kvadrerade residualerna d.v.s. variansen
inom och mellan stickprov för att kunna påvisa skillnader i väntevärde mellan
stickprov. De antaganden man gör i den här modellen är att alla observationer
är oberoende, alla observationer inom ett stickprov har samma varians och att
residualerna är normalfördelade. Metoden är ganska robust och brukar ge hyfsat bra resultat även om inte alla antaganden är uppfyllda. I MATLAB görs
ANOVA-test med hjälp av funktionen anova1. Som inparameter använder man
sig av en matris där varje kolumn är ett stickprov och som returvärde får man
ett p-värde, en tabell med underlaget för p-värdet och en boxplot. Nedan följer
ett kortare exempel där resultatet illustreras i figur 27:
>> y1 = [18.2, 20.1, 17.6, 16.8, 18.8, 19.7, 19.1];
>> y2 = [17.4, 18.7, 19.1, 16.4, 15.9, 18.4, 17.7];
>> y3 = [15.2, 18.8, 17.7, 16.5, 15.9, 17.1, 16.7];
>> M = [y1',y2',y3'];
>> anova1(M)
ans =
0.0373
5
STATISTIK I MATLAB
72
Figur 27: Boxplot av grupperna y1, y2 och y3.
5.3.5
Oparametriska test
Ibland är stickprovet inte normalfördelat och ibland tillhör datat ingen känd
statistisk fördelning alls. Då är det läge att använda sig av oparametriska test
eftersom de inte gör något fördelningsantagande.
ranksum: Funktionen jämför om två stickprov har samma medianer genom
att utföra Wilcoxons ranksummeringstest. Med den här metoden går det inte
att få ett konfidensintervall.
kruskalwallis: Funktionen gör en oparametrisk ANOVA genom att utföra ett
Kruskal-Wallistest.
5.3.6
Konfidensintervall
Med hjälp av funktionen paramci går det smidigt att skapa konfidensintervall.
För att funktionen ska kunna skapa ett konfidensintervall för µ måste den veta
vilken fördelning datat tillhör. Det betyder att vi först måste associera datat
med en specifik fördelning och i detta ändamål använder man sig av funktionen
fitdist. Antag att vi vill skapa ett konfidensintervall för temperaturdatat i
del 5.2.2 och antag att stickprovet är normalfördelat. För att då göra ett 95procentigt konfidensintervall skriver man:
>> pd = fitdist(temperature','normal');
>> ci = paramci(pd,'alpha',0.05)
ci =
50.8265
1.0726
5
STATISTIK I MATLAB
51.4802
73
1.5433
Den första kolumnen ger ett konfidensintervall för väntevärdet och den andra
ger ett konfidensintervall för standardavvikelsen. Kom ihåg att ett kort konfidensintervall nödvändigtvis inte är ett bra konfidensintervall. Det viktiga är att
man kan rättfärdiga antagandena som görs.
5.4
Programspråket R
Som ni märkt har MATLAB ett imponerande batteri av funktioner och rutiner
för att utföra statistisk analys. Trots det kan det ibland märkas att statistik
inte är MATLABs huvudfokus. Bland annat är det krångligt att hantera data
som innehåller information som inte kan översättas i siffror som exempelvis kön,
hårfärg, ort o.s.v. Därtill är mer avancerade statistiska metoder som flerdimensionella tester och bootstrapping relativt svåra att implementera i MATLAB.
Om man ska hålla på mycket med statistik kan därför programspråket R, se
figur 28, vara värt att prova. Dess syntax är väldigt lik MATLABs men istället
för att fokusera på matriser fokuserar R på statistik. Lite förenklat kan man
säga att R är statistikens MATLAB. R är ett open source alternativ som blivit
allt mer populärt såväl inom som utanför den akademiska världen och används
exempelvis i flera kurser som Institutionen för Matematik och Matematisk Statistik lär ut här i Umeå. Det kan laddas ned gratis på http://www.r-project.org/
och har en användbar editor kallad R-Studio som kan laddas ned gratis på
http://www.rstudio.com/.
Figur 28: R:s logga
6
KLASSISK MEKANIK MED MATLAB
6
74
Klassisk mekanik med MATLAB
Ett stort användningsområde för MATLAB är att utföra tunga beräkningar
och simuleringar. Idag har vanliga persondatorer tillräckligt med datorkraft för
att genomföra relevanta fysikaliska simuleringar. Traditionellt används datorns
CPU (Central Processing Unit) för att göra beräkningar, men i och med att
utvecklingen av grafikkort idag går snabbare än utvecklingen av CPU har det
även blivit intressant att använda datorns grafikkort för beräkningar.
6.1
Newtons rörelseekvationer med numeriska metoder
I denna del kommer vi att beskriva hur man kan använda MATLAB för att simulera ett fysikaliskt system. Mer specifikt tänkte vi visa hur man löser Newtons
andra lag och med hjälp ut av den kunna beskriva ett objekts rörelse givet de
krafter som verkar med objektet och initialvillkor. Detta kommer vi göra genom
att använda oss av numeriska metoder. Det innebär, till skillnad från att lösa
problemet analytiskt, att vi delar upp vår lösning i ett bestämt antal diskreta
steg. Sedan löser vi våra fysikaliska ekvationer för alla dessa steg med någon typ
av uppskattning av en derivata, integral eller vad det nu är vi vill lösa.
6.1.1
Rörelse i en dimension
Vi börjar med att studera rörelse i en dimension och när vi löst det endimensionella fallet, kan vi enkelt generalisera lösningen till två eller tre dimensioner.
Antag att vi har ett föremål med position x, hastighet v och acceleration
a. Vi vill beräkna hur föremålets position förändras över tiden, givet att vi vet
föremålets position och hastighet vid tiden t = 0. Accelerationen hos ett föremål
beskrivs av Newtons andra lag
F
,
(10)
m
där F är kraften som påverkar föremålet, m är föremålets massa och a är
föremålets acceleration. Sådana här mindre ekvationer kan fördelaktigt representeras med anonyma funktioner i MATLAB, se avsnitt 2.3 för repetition.
Accelerationen definieras som andraderivatan av positionen med avseende
på tiden enligt
d2 x
a= 2.
(11)
dt
Om vi känner till kroppens position och hastighet vid tiden t = 0 samt om
dess acceleration, eller den totala kraften som verkar på kroppen, är en känd
funktion, kan vi lösa ovanstående differentialekvation och se hur positionen x
varierar med tiden. För vissa problem går ekvationen att lösa för hand, men för
mer avancerade problem eller problem med många föremål som rör sig samtidigt
är ofta den enda lösningen att använda sig av datorhjälpmedel och numeriska
metoder.
Ekvation (11) är en andra ordningens differentialekvation. Den går att skriva
om som två kopplade första ordningens differentialekvationer genom att införa
hastigheten v som hjälpvariabel. Problemet som ska lösas blir då
(
dx(t)
dt = v(t)
(12)
dv(t)
dt = a(t)
F = ma → a =
6
KLASSISK MEKANIK MED MATLAB
75
där initialvärden x(0) = x0 och v(0) = v0 är kända, och a(t) är en känd funktion.
Både ekvation (11) och (12) beskriver samma fysik. Numeriskt är det ofta lättare
att hantera första ordningens differentialekvationer så vi kommer använda ekvation (12) som grund för våra simuleringar. Notera att den numeriska metoden
vi ska använda förutsätter att kraften F är konservativ. 2
För att lösa problemet numeriskt diskretiserar vi det. Vi börjar med att
dela in tiden i diskreta punkter t0 , t1 , t2 ..., tn , tn+1 , .... Mellan varje punkt råder
konstant tidsskillnad ∆t så att t0 = 0, t1 = ∆t,t2 = 2∆t, ..., tn = n∆t.
För att förenkla notationen kommer vi använda beteckningen xn för x(tn )
och v n för v(tn ) o.s.v. Den numeriska metoden kommer att hitta en approximativ lösning till ekvation (12). Grundidén är att om vi vet var vi är vid tiden
tn kan vi approximera var vi kommer vara vid tiden tn+1 och på så sätt stega
oss framåt i tiden. Detta gör vi genom att approximera tidsderivatan, alltså
en förändring av positionen med avseende på tid i en viss punkt. Vi kan t.ex.
approximera förändringen i x vid tiden tn med
x(tn + ∆t) − x(tn )
xn+1 − xn
dx
≈
=
dt
∆t
∆t
(13)
som är derivatans definition om vi låter ∆t → 0. Steglängden ∆t avgör hur bra
approximationen blir och vi ser att om ∆t → 0 blir derivatan exakt. Men om vi
tar väldigt små tidssteg kommer simuleringen att ta lång tid eftersom vi måste
ta fler steg för att simulera en given total tid. Konsten är att välja ett ∆t som
är litet nog för att ge en bra approximation, men samtidigt inte för litet så att
simuleringen tar orimligt lång tid att köra.
En något bättre metod är att använda
dx
x(tn + ∆t) − x(tn − ∆t)
xn+1 − xn−1
≈
=
(14)
dt
2∆t
2∆t
som använder ett tidigare och ett senare tidssteg för att räkna ut derivatan.
En mer avancerad och ännu bättre integrationsmetod heter Velocity-Verlet,
och bygger på två rekursiva uppdateringsformler som används för att stega
framåt i tiden. De två formlerna, en för positionen och en för hastigheten, är
n+1
2
x
= xn + v n ∆t + 21 an ∆t
(15)
v n+1 = v n + 21 an + an+1 ∆t
För att demonstrera Velocity-Verlet metoden skulle vi kunna använda oss
utav ett exempel med ett objekt med en massa m fastspänd i en masslös fjäder
med fjäderkonstant k utan dämpning, se figur 29. Objektet släpps sedan stillastående från ett avstånd x0 från jämviktsläget. Kraften som verkar på objektet
från fjädern får vi från Hookes lag
k
x
m
där x är objektets förskjutning från fjäderns jämviktsläge.
F = −kx → a = −
(16)
2 En konservativ kraft är en sådan kraft att arbetet den uträttar är vägoberoende och
beror alltså bara på start- och slutposition. Gravitationskraft och coulumbkraft är exempel
på konservativa krafter, medan friktionskraft är ett exempel på en dissipativ kraft, vilket är
motsatsen till en konservativ krafter.
6
KLASSISK MEKANIK MED MATLAB
76
Figur 29: Massa m fastspänd i masslös fjäder med fjäderkonstant k.
Nedan följer ett exempel på hur man kan lösa detta problem med metoden
ovan:
function osc(m,k,x0,dt,tmax)
%Function that simulates an oscillating object attached to a spring. In
%parameters: m=mass of the object, k=spring constant, x0=object's distance
%from equilibrium, dt=timestep, tmax=simulation time
%Calculating number of steps in simulation
steps=tmax/dt;
%Create vector conating each time−step
t=linspace(0,tmax,steps);
%Creating function to calculate force on object
ac = @(x) −k*x/m;
%Allocate memory
x=zeros(steps,1);
v=zeros(steps,1);
a=zeros(steps,1);
%Set initial conditions
x(1)=x0;
v(1)=0;
a(1)=ac(x0);
for i=1:(steps−1)
%Update position
x(i+1)=x(i)+v(i)*dt+1/2*a(i)*dtˆ2;
%Update acceleration
a(i+1)=ac(x(i+1));
%Update velocity
v(i+1)=v(i)+1/2*(a(i)+a(i+1))*dt;
end
%Plot the objects distance from the equilibrium over time
plot(t,x);
title('Oscillating object')
xlabel('Elapsed time (t)')
ylabel('Distance from equilibrium(x)')
end
Plotten som programmet producerar med m = 10kg, k = 0.5 N/m, x0 = 0.1,
dt = 0.1 s och tmax = 100 s kan ses i figur 30.
6
KLASSISK MEKANIK MED MATLAB
77
Oscillating object
Distance from equilibrium (x)
0.1
5 · 10−2
0
−5 · 10−2
−0.1
0
10
20
30
40
50
60
70
80
90
100
Elapsed time (t)
Figur 30: Figur producerad av MATLAB-exemplet ovan.
Skulle man vilja utöka exemplet med att till exempel lägga till en dämpning i
fjädern så är det bara att ändra i definitionen av kraften som verkar på objektet.
En härledning av Velocity-Verlet-metoden finns i avsnitt 6.2, läs gärna igenom den. Det är bra om man vet vilka antaganden som ligger bakom en metod
man använder så man inte råkar ut för överraskningar.
6.1.2
Rörelse i flera dimensioner
Systemet kan utökas till fler dimensioner; rörelsen i de olika riktningarna är
bara kopplade genom kraften som är positionsberoende och i övrigt är rörelsen
i de olika riktningarna oberoende av varandra. För två dimensioner får vi fyra
uppdateringsekvationer x, y, vx och vy , enligt
 n+1
x
= xn + vxn ∆t + 12 anx ∆t2


 n+1
2
y
= y n + vyn ∆t + 21 any ∆t
.
(17)
1
n+1
n
n
n+1
vx
= vx + 2 ax + ax ∆t


 n+1
vy
= vyn + 21 any + an+1
∆t
y
Mer allmänt kan vi skriva om uppdateringsrelationerna på vektorform som
n+1
= rn + vn ∆t + 21 a(rn )∆t2 r
,
(18)
n+1
v
= vn + 21 a(rn ) + a(rn+1 ) ∆t
där r är positionsvektorn, v är hastighetsvektorn och a(r) är en känd funktion
som beräknar accelerationsvektorn utifrån en given positionsvektor. Ekvationerna ovan gäller för rörelsen av en enskild kropp, men vi kan utöka dem till
6
KLASSISK MEKANIK MED MATLAB
78
att gälla flera kroppar. Antag att vi har två kroppar med positionerna r1 och
r2 som växelverkar genom accelerationen, d.v.s. a(r1 , r2 ). Då får vi följande
ekvationssystem:
 n+1
= rn1 + v1n ∆t + 21 a1 (rn1 , rn2 )∆t2

1
 rn+1

r2
= rn2 + v2n ∆t + 21 a2 (rn1 , rn2 )∆t2
.
(19)
n+1
n+1 n+1
1
n
n n

 v1n+1 = v1 + 2 a1 (r1 , r2 ) + a1 (r1n+1 , r2n+1 ) ∆t

v2
= v2n + 21 a2 (rn1 , rn2 ) + a2 (r1 , r2 ) ∆t
Har man fler kroppar är det bara att fortsätta lägga till fler ekvationer. Det ser
mycket ut när man skriver ut ekvationerna så här men när man programmerar
behöver man bara skriva in ekvationerna en gång. Har man flera kroppar i sitt
system löser man det med en loop se avsnitt 2.2, eller ännu hellre, ordnar datat i
vektorer där man låter varje element i vektorn representera en kropp. Använder
man vektoriseringen kan man med fördel använda MATLABs inbyggda vektoroperationer se avsnitt 2.1.3. Alltså är skillnaden från exemplet i en dimension
att det adderas två nya ekvationer per dimension, t.ex. för två dimensioner är
det bara de fyra uppdateringsformlerna i ekvation (17) som behövs användas.
6.2
Verlet-integration
Vi ska nu härleda en metod för att integrera accelerationen och beräkna banan
som ett föremål kommer att följa. Notera att det här kapitlet kan vara lite
knepigt att förstå fullt ut och det är inte nödvändigt att förstå i detalj för att
använda metoden. Det kan däremot vara bra att läsa igenom för att få lite
förståelse för hur den fungerar.
Vi börjar med att anta att föremålets position och hastighet vid t = 0 är
kända. Vi utgår från Newtons andra lag,
F (x(t))
d2 x
= a(x(t)) =
,
dt2
m
(20)
där F (x(t)) är en konservativ kraft som endast beror på positionen x. Vi diskretiserar tiden och approximerar andraderivatan enligt följande:
a(x) =
d2 x
≈
dt2
xn+1 −xn
∆t
n
−x
∆t
−xn−1
∆t
=
xn+1 − 2xn + xn−1
= an .
∆t2
(21)
Om vi löser ut xn+1 får vi
xn+1 = 2xn − xn−1 + an ∆t2
(22)
vilket är en fullt fungerande integrationsmetod som kan användas för att räkna
ut framtida positioner xn+1 givet de två föregående positionerna xn och xn−1
samt accelerationen. Metoden har utvecklats flera gånger av olika forskare genom historien. Den kallas oftast Verlets metod efter den senaste upphovsmannen
som gjorde metoden känd, men man kan även se andra namn som t.ex. Störmers
metod. Verlets metod använder bara positionen och accelerationen vid en given
tidpunkt för att räkna ut nästa position och använder inte den momentana hastigheten. Detta har både för och nackdelar beroende på vilken typ av problem vi
vill lösa. Om vi inte behöver känna till hastigheten är metoden mycket effektiv
6
KLASSISK MEKANIK MED MATLAB
79
eftersom det går att räkna ut positionen direkt utan att gå omvägen via hastigheten. Men om vi behöver hastigheten blir det lite omständligt. Hastigheten i
en given position xn går att räkna ut från skillnaden mellan två positioner som
omgärdar den i tid, enligt
vn =
xn+1 − xn−1
,
2∆t
(23)
men vi ser att för att räkna ut denna hastigheten v n måste vi redan känna till
nästkomande positionen xn+1 , vilket inte alltid är praktiskt. En annan sak att
tänka på är att man oftast bara känner till position x0 , alltså positionen vid
t = 0, så för att komma igång måste xn−1 först beräknas med hjälp av någon
annan metod. För att Verlet-metoden ska fungera måste ∆t vara konstant under
hela simuleringen. Ändrar man tidsteget under simuleringen kommer partikelns
rörelse att bli felaktig om man inte samtidigt skalar om de andra termerna för
att kompensera för förändringen.
6.2.1
Velocity-Verlet
Det går att skriva om Verlets metod så att man får ut hastigheten direkt.
Metoden kallas då Velocity-Verlet. Det är en populär metod som ofta används
för att simulera rörelsen hos t.ex. molekyler. Vi utgår ifrån den vanliga Verletmetoden och börjar med att lösa ut xn−1 från ekvation (23). Vi får då
xn−1 = xn+1 − 2v n ∆t.
(24)
Vi sätter in uttrycket för xn−1 i ekvation (22) vilket ger
1
xn+1 = xn + v n ∆t + an ∆t2 ,
2
(25)
som är en ny uppdateringsmetod för positionen som även beror på hastigheten.
Men för att få en fungerande metod behöver vi även veta hur vi ska uppdatera
hastigheten. Utifrån ekvation (23) kan vi sätta upp ett uttryck för v n+1 :
v n+1 =
xn+2 − xn
.
2∆t
(26)
Vi kan ta fram uttryck för xn+2 och xn från ekvation (25) och sätta in dem i
ekvation (26) vilket ger
xn+1 + v n+1 ∆t + 12 an+1 ∆t2 − xn+1 − v n ∆t − 21 an ∆t2
n+1
v
=
,
(27)
2∆t
vilket efter förenkling blir
v n+1 = v n +
1 n
a + an+1 ∆t.
2
Vi har nu två uppdateringsekvationer
n+1
2
x
= xn + v n ∆t + 21 an ∆t
1
n+1
n
n
n+1
v
= v + 2 a +a
∆t
(28)
(29)
som tillsammans utgör metoden vi kallar Velocity-Verlet. Metoden är självstartande,
d.v.s. vi behöver inte använda en separat metod för att beräkna xn−1 eftersom
6
KLASSISK MEKANIK MED MATLAB
80
det värdet aldrig används till skillnad från i den vanliga Verlet-metoden. Även
Velocity-Verlet kräver ett konstant ∆t för att fungera korrekt. Man bör också
vara medveten om att metoden bygger på antagandet att kraften är konservativ,
d.v.s. att kraften går att skriva som gradienten av en potential, F = −∇V (r),
där r är positionsvektorn, och V är en funktion som beskriver den potentiella
energin i systemet.
Slutligen kan nämnas att det finns en annan populär metod som kallas Leapfrog som också går att härleda genom att göra en omskrivning av Verletmetoden. Velocity-Verlet och Leapfrog är väldigt lika och har i princip samma
egenskaper.
A
APPENDIX: RAPPORTSKRIVNING MED MATLAB
A
81
Appendix: Rapportskrivning med Matlab
Nästan alla kurser på Teknisk fysik innehåller på ett eller annat sätt laborationer
och en stor del av dessa är att skriva rapporter. I detta appendix kommer vi att
gå igenom de mest användbara sakerna som gör det enklare för dig att producera
snygga och bra labbrapporter.
A.1
Bilder i MATLAB
I denna del tänkte vi utöka kunskapen från kapitel 1.6 och visa på lite fler saker
som man kan göra för att förändra sina figurer.
A.1.1
Plot-kommandot
Till att börja med tänkte vi visa på lite inparametrar till plot-kommandot som
man kan använda för att ändra utseendet på sina plottar.
Färg: För att bestämma färgen på sin plot mer specifikt använder vi oss
av RGB-färgvärdet där RGB står för rött, grönt och blått. RGB-färgvärdet
bestämmer hur mycket av varje färg som ska emitteras och anges som ett värde
mellan 0 och 1. Ett exempel som ger en blågrön nyans är:
plot(x,y,'Color',[0,0.7,0.9])
Linjebredd: Bredden på linjen anges i punkter där en punkt är ungefär 0.35
mm. För att byta linjebredd på sin plott skriver man:
plot(x,y,'LineWidth',0.75).
Linjestil: Man kan även byta stil på linjen som man plottar, nedan listas de
olika alternativ som finns.
’-’ (standard) ’- -’ ’-.’ ’:’ ’none’ (ingen linje)
För att implementera detta skriver man:
plot(x,y,':')
Markörer: Ofta när man använder plottar är det för att visualisera mätpunkter.
För att markera dess tydligt kan man använda sig av de olika alternativen som
listas nedan.
’o’ ’+’ ’*’ ’.’ ’pentagram’ eller ’p’
’square’ eller ’s’
’∧ ’
’v’ ’<’ ’>’ ’x’ ’hexagram’ eller ’h’ ’diamond’ eller ’d’ ’none’
För att implementera detta skriver man:
plot(x,y,'+').
Skulle vi kombinera alla saker nämnda ovan skriver man
plot(x,y,'x−.','LineWidth',1,'Color',[0,0.7,0.9])
och vi få något som ser ut så som figur 31.
A
APPENDIX: RAPPORTSKRIVNING MED MATLAB
82
2-D Line Plot
1
sin(x)
0.5
0
−0.5
−1
0
2
4
6
8
10
x
Figur 31: Sinuskurva skapad i MATLAB
Det finns även möjlighet att ändra kantfärgen, fyllningsfärg och storleken på
markörerna vilket görs genom att lägga till t.ex:
'MarkerEdgeColor',[0.1,0.2,0.3]
'MarkerFaceColor',[0.5,0.5,0.5])
'MarkerSize', 10
Färgen bestäms av samma RGB-värde som för linjefärgen och storleken bestäms
i samma enhet som för linjebredden.
A.1.2
Sub-plottar
Ibland räcker det inte med en plot för att presentera sitt resultat utan man vill
ha flera stycken. För att fortfarande ha alla dessa i samma figurer är subplotkommandot användbart.
Subplot(m,n,p) delar in figuren i rutnät med m × n platser där varje plats
innehåller en plot. p specificerar platsen i rutnätet som är radnumrerat, det vill
säga plats 1 är rad 1 kolumn 1, plats 2 är rad 1 kolumn 2 o.s.v.
Vi skulle exempelvis kunna skriva:
subplot(2,2,1)
plot(x,cos);
title('Cos(x)')
subplot(2,2,2)
plot(x,sin)
title('Sin(x)')
subplot(2,2,3)
plot(x,e)
title('eˆx')
subplot(2,2,4)
A
APPENDIX: RAPPORTSKRIVNING MED MATLAB
83
plot(x,ln)
title('ln(x)')
matlab2tikz('sub.tikz')
Den resulterande figuren ses i figur 32.
Cos(x)
Sin(x)
1
1
0.5
0.5
0
0
−0.5
−0.5
−1
0
2
4
6
e
·104
8
10
−1
0
2
4
6
ln(x)
8
10
0
2
4
8
10
x
4
2
2
0
1
−2
0
0
2
4
6
8
10
−4
6
Figur 32: Figur med fyra sub-plottar
A.1.3
Symboler
När man skriver titlar, axelnamn m.m. är det ibland nödvändigt att använda
olika symboler t.ex. grekiska bokstäver eller matematiska tecken. Nedan, i tabell
4, listas symboler som man kan finna användbara där sekvensen är den del som
man lägger till i strängen för att skapa symbolen.
A
APPENDIX: RAPPORTSKRIVNING MED MATLAB
Tabell
Symbol
α
β
γ
δ
ζ
η
θ
ι
κ
λ
µ
ν
ξ
π
ρ
σ
τ
υ
φ
χ
qψ
ω
84
4: Matematiska symboler och hur man skriver dem i MATLAB.
Sekvens
Symbol
Sekvens
Symbol
Sekvens
\alpha
∗
\ast
∝
\propto
\beta
≡
\equiv
∂
\partial
\gamma
⊃
\supset
•
\bullet
R
\delta
\int
÷
\div
\epsilon
⊥
\perp
ℵ
\aleph
\zeta
∧
\wedge
⇐
\Leftarrow
\eta
∨
\vee
⇒
\Rightarrow
\theta
h
\langle
∇
\nabla
\iota
i
\rangle
∃
\exists
\kappa
⊆
\subseteq
∀
\forall
\lambda
∈
\in
±
\pm
\mu
·
\cdot
...
\ldots
\nu
6=
\neq
|
\mid
√
\xi
\surd
0
\prime
∼
\pi
\cong
<
\Re
=
\rho
≈
\approx
←
\leftarrow
\sigma
∼
\sim
→
\rightarrow
\tau
≤
\leq
↔
\leftrightarrow
\upsilon
≥
\req
↑
\uparrow
\phi
∞
\infty
↓
\downarrow
\chi
℘
\wp
×
\times
\psi
\oslash
Nedsänkttext Nedsänkt {text}
\omega
◦
\circ
Upphöjdtext Upphöjd∧ {text}
Om man söker den versala varianten av en grekisk bokstav byter man första
bokstaven i sekvensen till en versal. Om man söker en annan variant än den som
finns tabulerad kan man lägga till prefixet var till sekvensen t.ex. \vartheta
ger ϑ.
A.2
MATLAB med andra program
Nu är det så att MATLAB inte är den enda användbara mjukvaran som man
använder sig av på Teknisk fysik. I denna del nämner vi några andra användbara
program och hur man kan integrera dessa med MATLAB.
A.2.1
MATLAB2tikZ
När man väl har fått sin plot bra i MATLAB och vill överföra den till sin rapport
kan det ibland hända att det inte blir som man vill. Om man skriver sin rapport
i LaTeX så kan man undvika många av de här problemen genom att använda
scriptet MATLAB2tikZ som konverterar MATLAB-figurer till tikZ-filer. TikZ
är ett paket till latex som hjälper till att skapa sofistikerad grafik.
För att göra detta måste man först ladda ner scriptet MATALAB2tikZ från
mathworks.com. När nedladdningen är klar lägger man M-filerna där MATLAB
hitta dem. För att sedan generera den tikz-fil som ska in i rapporten anropar
man matlab2tikz('MyFile.tikz') efter plot-kommandot. Det borde nu ha
skapats en fil med namnet M yF ile.tikz.
A
APPENDIX: RAPPORTSKRIVNING MED MATLAB
85
För att lägga till bilden i rapporten måste man först lägga till paketet
\usepackage{pgfplots} överst i LaTeX-filen. Sedan lägger man tikz-filen i samma
mapp som sitt rapportdokument och lägger in bilden i rapporten genom att
skriva \input{myfile.tikz} där man vill ha den.
En stor fördel med denna metod är att man nu kan gå in i skapade tikzfiler med hjälp av en vanlig textredigerare, till exempel Notepad i Windows och
ändra utseendet på sin plot. Man kan t.ex. ändra storlek, namn och storlek på
axlar, namn på titlar, färger m.m. Det finns mycket information om vad som
går att göra med tikz-filen på mathworks egna hemsida eller olika forum.
Om man skulle vilja addera till exempel figurtexter kan man lägga till figurmiljön som vanligt. Det skulle kunna se ut såhär:
\begin{figure}
\centering
\input{MyFile.tikz}
\caption{Sinuskurva}
\label{Sinus}
\end{figure}
A.2.2
MATLAB med COMSOL
COMSOL Multiphysics är en mjukvara som använder sig av numeriska metoder
för att modellera och simulera olika fysikaliska problem. COMSOL kan användas
för att beräkna problem i t.ex. flödesmekanik, hållfasthetslära eller elektromagnetism. Dessutom kan COMSOL koppla ihop modeller från olika områden vilket
gör den väldigt användbar.
MATLAB och COMSOL kan integreras väldigt väl med hjälp av LiveLink
for MATLAB som förlänger COMSOLs gränssnitt till MATLAB. Med detta
kan man skapa modeller med hjälp av script i MATLAB eller analysera resultat
i MATLAB m.m. Vill man veta mer om detta hänvisar vi till Google. Istället
tänkte vi ge ett kort exempel på hur man kan föra över data från COMSOL till
MATLAB på smidigt sätt.
Säg att man har gjort sin modell i COMSOL, fått den data man vill ha
i tabell-format och exporterat den till en txt-fil. För att öppna den i MATLAB sparar man txt-filen där MATLAB kan hitta den och importer den genom
att skriva ComsolImport=importdata('myFile.txt'). Tillbaka får man en
strukt innehållande två delar; data och textdata. I data finns en matris med
alla värden som man fått fram i Comsol. Dessa värden är uppradade i kolumnvektorer och i textdata finns information om filen bl.a. namnen på de olika
variablerna.
Om vi t.ex. har räknat värdet för den beroende variabel y och för värdet på
den oberoende variabel x kan vi skriva:
ComsolImport=importdata('myFile.txt')
data=ComsolImport.data
x=data(:,1)
y=data(:,2)
A
APPENDIX: RAPPORTSKRIVNING MED MATLAB
A.3
86
Feluppskattningar
Vi har tidigare nämnt, i del 1.7, en metod för att göra en regressionsanalys
och tänkte här beskriva ett annat sätt som gör att man enkelt kan plocka ut
konfidensintervall för de koefficienter som analysen ger.
Funktionen som vi tänkte ta upp i denna del är fit(x,y,fitType). Här
står x för den oberoende variabeln, y för den beroende variabeln och fitType
bestämmer vilken typ av regression man vill göra. För att göra en polynomisk
anpassning skriver man polyn där n är ordningen på sitt polynom. Det går också
att använda denna funktionen för att anpassa en polynomisk yta, då måste den
oberoende variabeln vara en 2 × k-matris där k är antalet mätvärden och man
skriver 'polynm' där n är ordningen på den första variabeln och m ordningen
på den andra.
Givet att vi har mätpunkter i F beroende på x kan vi skriva som nedan för
att göra vår regressionsanalys:
x=0:0.05:0.45;
F=[0 0.4 0.87 1.35 1.82 2.29 2.78 3.24 3.7 4.19];
[fitobject gof]=fit(x',F','poly1')
Den utskrift vi får är de uppskattade koefficienterna till linjäranpassningen med
ett 95%-konfidensintervall. Om man önskar att få en annan procentsats på konfidensintervallet för koefficienterna kan man skriva confint(fitobject,1−a)
där a är det konfidensintervall man vill ha. Om vi exempelvis skulle vilja veta
de koefficienterna ovan med ett 99% konfidensintervall skriver man:
confint(fitobject, 0.01)
’gof’-variabeln eller goodness-of-fit innehåller data på hur bra modellen är anpassad till mätvärdena, här hittar man bland annat R2 -värdet och R2 − adjust.
Skulle man nu vilja plotta sina mätvärden med sin regression skriver man
plot(fitobject,x',F').
B
APPENDIX: VANLIGA FEL
B
87
Appendix: Vanliga fel
I detta appendix kommer vi ta upp vanliga fel, dess felmeddelanden och hur
man undersöker dem för att förstå vad man gjort fel. En del fel är vanligare och
kommer gå fortare att känna igen medan en del andra bara händer ibland och
därför inte är lika lätta att identifiera i början. Vi kommer även gå igenom hur
man på ett enkelt sätt felsöker sin kod. Detta kommer vi göra både genom att
manuellt felsöka koden och genom att använda MATLABs inbyggda debuggerverktyg.
B.1
Dimensionsfel
Bland de vanligaste felen man får i MATLAB är dimensionsfel eftersom man så
ofta arbetar med vektorer och matriser. Dimensionsfel kallas de fel som uppstår
då man försöker utföra operationer som inte är genomförbara med de dimensioner som man arbetar med. Om man försöker multiplicera en vektor med en
matris elementvis får man detta felmeddelande:
>> A = [1 2 3 ; 4 5 6 ; 7 8 9];
>> b = [1 2 3];
>> A.*b
Error using .*
Matrix dimensions must agree.
Detta beror på att vektorn och matrisen inte har samma dimensioner. För att
multiplicera en vektor med en matris måste vi använda oss utav matrismultiplikation, men ibland blir även det fel:
>> A*b
Error using *
Inner matrix dimensions must agree.
Den här gången beror felet på att radvektor inte går att multiplicera med en matris. Om vi istället tar kolumnvektorn genom att transponera vektorn fungerar
det:
>> A*b'
ans =
14
32
50
Ett liknande fel uppstår om man försöker upphöja en vektor med 2 och
glömmer punkten som representerar elementvisa operationer:
>> bˆ2
Error using ˆ
Inputs must be a scalar and a square matrix.
To compute elementwise POWER, use POWER (.ˆ) instead.
B
APPENDIX: VANLIGA FEL
88
Eftersom detta är ett relativt vanligt fel och inte kan bero på så många olika
anledningar får man av MATLAB ett exempel på vad man förmodligen menade,
att använda den elementvisa operationen.
Man kan även få dimensionsfel när man försöker tilldela två element till en
position:
>> A(1,2) = [2 3]
Subscripted assignment dimension mismatch.
Om man försöker plotta två vektorer med olika längd mot varandra får man
följande fel:
>> f = [13 16 6 15];
>> time = [1 2 3];
>> plot(time, f)
Error using plot
Vectors must be the same lengths.
Även här är det ganska tydligt vad man gjort fel. Det som kan vara svårt är
att veta varför vektorerna man skapat har olika längder om man t.ex. skapar
vektorerna i loopar.
När det gäller dimensionsfel, oberoende av vilken sort, är den enklaste lösningen
att skriva ut längden på vektorn och/eller storleken på matrisen med length
och size för att på så vis hitta varför operationen inte fungerade.
B.2
Indexeringsfel
Efter dimensionsfel är nog indexering det man oftast gör fel på. Med dessa fel
är det en aningen lättare att inse vart problemet uppstår. Det man har gjort då
man får fel på grund utav indexeringen är att man antingen försöker komma åt
index som inte finns eller som är ogiltiga. Exempel på ogiltiga index är negativa
index eller tal som inte är heltal:
>> A(0.5)
>> A(−1)
Subscript indices must either be real positive integers or logicals.
Felmeddelandet som man får säger tydligt varför man inte får använda 0.5 eller
-1 som index. 0 är i MATLAB inte ett giltigt index eftersom det första indexet
i MATLABs vektorer är 1. Detta kanske är relativt enkelt att komma ihåg då
man skapar vektorer i början men problem kan uppstå när man i en loop t.ex.
vill spara undan tiden i sekunder från 0 till 10:
for i=0:10
time(i) = i;
end
Attempted to access (0); index must be a positive integer or logical.
I detta fall måste man istället spara tiden 0 i index 1, vilket fungerar med raden:
time(i+1) = i;
B
APPENDIX: VANLIGA FEL
89
Andra indexfel man gör är att man försöker komma åt index som inte existerar i sin vektor. T.ex. om man har en vektor som består av 5 element men
försöker komma åt element 6:
>> x=1:5;
>> x(6)
Index exceeds matrix dimensions.
for i= 1:6
x(i)*2;
end
Attempted to access x(6); index out of bounds because numel(x)=1.
I det här fallet får man två olika felmeddelanden beroende på om man vill
skriva ut eller använda elementet. Innebörden är dock den samma, det finns
inget värde på plats 6 i en vektor med längden 5.
När det gäller indexeringsfel får man fundera på varför man försöker komma
åt ett element som inte existerar. Kanske har man sparat sina vektorer på ett
annat sätt än vad man trodde. Även här är det bra med length och size för
att undersöka problemet.
B.3
Syntaxfel
Syntaxfel är ofta fel som inte ens behöver förklaras men för ordningens skull
tar vi upp några sådana också. Om man skriver ett uttryck som MATLAB inte
förstår kommer MATLAB klaga:
>> A = 1+3+
|
Error: Expression or statement is incomplete or incorrect.
I detta fall har vi ett inkomplett uttryck, antingen är det ett plustecken för
mycket eller ett tal för lite. Andra fel kan vara tecken som inte existerar i
MATLAB:
>> `
|
Error: The input character is not valid in MATLAB statements or expressions.
>> A(1::, 2)
|
Error: Unexpected MATLAB operator.
Ovanstående exempel innebär samma fel men ger olika felmeddelanden beroende
på om det är tecken som MATLAB kan hantera i huvudtaget eller inte. I det
senare exemplet klagar MATLAB på grund av det dubbla kolon-tecknet. Ett
kolon är en giltig MATLAB-operation, men inte två efter varandra. Vanliga
fel som uppstår då man har lite bråttom är att man glömmer parenteser eller
använder dem där det inte fungerar:
>> f = (3*4)+5);
B
APPENDIX: VANLIGA FEL
90
Error: Expression or statement is incorrect−−possibly unbalanced (, {, or [.
>> A(1))
|
Error: Unbalanced or misused parentheses or brackets.
Ett lite mer oklart syntaxfel man kan göra är att t.ex. använda bara ett
likhetstecken då man vill ha två:
>> a = 2;
>> if a = 3
if a = 3
|
Error: The expression to the left of the equals sign is not a valid
target for an assignment.
MATLAB tolkar detta som att man försöker tilldela a värdet 3 då man egentligen vill undersöka om a är lika med 3.
När det gäller syntaxfel är det generellt sett bara att ändra det som står i
felmeddelandet så kommer det lösa sig. Eventuellt att det kan vara svårt att
räkna parenteserna om det är många men då gäller det bara att vara noggrann.
Ett tips kan vara att först skriva ut parenteserna och sedan det som ska vara
innanför.
B.4
Övriga fel
Här nedan har vi samlat en del övriga fel som kan uppstå. Övriga fel i MATLAB
kan vara allt från att anropa felstavade funktioner till att försöka läsa in filer
som ligger i fel mapp. Ett vanligt fel kan vara att man glömmer att MATLAB
skiljer på stora och små bokstäver:
A = [1 4 53 3];
T = [1 2 3 4];
A(t)
Undefined function or variable 't'.
Funktionen t anses odefinierad eftersom den inte existerar. På samma sätt blir
det fel om man försöker anropa en funktion med felaktigt namn:
>> A = [1 2; 1 4]
>> eigenvalue = eigen(samplemat);
Undefined command/function 'eigen' for input arguments of type 'double'.
I detta fall är det eig som man vill använda, det finns ingen inbyggd MATLABfunktion som heter eigen. Andra fel man kan göra vid funktionsanrop är att
ange för få eller för många inparametrar:
>> A = plus(1,2,3)
Error using +
Too many input arguments.
>> A = ode45()
Error using ode45
Not enough input arguments.
See ODE45.
B
APPENDIX: VANLIGA FEL
91
I det övre fallet vill plus ha två inparametrar för att utföra addition och i
det nedre exemplet vill ODE45 ha minst en inparameter. Man kan även försöka
komma åt fler returvärden än vad funktionen returnerar:
>> A = [1,2;3,4]
>> [V,D,Mistake] = eig(A);
Error using ==> eig
Too many output arguments.
Funktionen eig har endast två returvärden och frågar man efter tre får man
ovanstående felmeddelande.
Andra fel man kan göra är att döpa en funktionsfil till något annat än funktionsnamnet eller försöka läsa in en fil som inte ligger i samma mapp. Om man
döper en funktionsfil till ett annat namn än funktionsnamnet kan man få felmeddelandet:
>> function name(3)
Undefined function 'function name' for input arguments of type 'double'.
Felmeddelandet säger att funktionen function name inte är definierad trots att
vi precis skapat den, dock är den sparad i en M-fil som heter file.m. Problemet är
att MATLAB inte förstår att vi skapat en funktion med det namnet utan väntar
på ett anrop till file.m. Lösningen är att ändra filnamnet till function name.
Om man försöker läsa in en fil som ligger i en annan mapp får man felmeddelandet:
>> A = load('numbers.txt')
Error using load
Unable to read file numbers.txt: No such file or directory.
Lösningen är att antingen flytta M-filen eller textfilen till den mapp där man
vill spara sitt material.
B.5
Felsökning i MATLAB
De vanliga felen som vi har listat här ovan går ofta att lösa genom att ändra
något på samma rad som MATLAB klagar på. Andra fel, de så kallade logiska
felen som gör att programmet inte gör det man vill, måste man själv hitta. Dessa
fel är både svåra att hitta och förstå att man har om man inte kontinuerligt
testar sin kod. När man förstått att man har fel i sin kod och vill undersöka
vart problemen uppstår kan man antingen manuellt felsöka koden eller ta hjälp
av MATLABs inbyggda debugger.
B.5.1
Felsökning i MATLAB
Att felsöka sin kod är något man lär sig allt eftersom man gör det. Det handlar
om vana och att veta vilka problem som kan uppstå. Det underlättar också om
man vet själv vad man ofta gör fel på och kan titta igenom sådana kodstycken
tidigt. I felsökning finns det inget som är rätt och fel utan alla gör olika. Här
kommer vi ge lite generella tips på hur man ska gå till väga för att hitta felen.
När man felsöker sin kod är det bra att börja med att översiktligt kolla igenom koden för att se hur man byggt upp sitt program och om man ser några
B
APPENDIX: VANLIGA FEL
92
självklara fel, något kanske kommer i fel ordning t.ex. Nästa steg är att systematiskt gå igenom koden, först lite mer översiktligt och om man inte hittar felet
första vändan, köra en till sväng då man är lite mer noggrann. Det viktigaste
är att man är systematisk så man vet att när man gått igenom en sekvens i sin
kod så fungerar den som det är tänkt.
Om man inte hittar felen direkt kan man använda sig utav kommandot
keyboard. För att använda detta kommando skriver man in det i sin kod och
när man kör koden kommer MATLAB att stanna vid raden där man skrivit
keyboard. Det man kan göra är då att i kommandofönstret undersöka vad
variablerna för tillfället är:
B = zeros(4,1);
for i=1:3
B(i,1) = i;
keyboard
end
K>> B
B =
1
0
0
0
I ovanstående exempel avbryts körningen efter ett varv i loopen. Vektorn B
har alltså bara hunnit ändra sitt första värde. K:et framför kommandopromten
indikerar att man har aktiverat keyboard-läget. För att fortsätta i filen skriver
man return i kommandofönstret:
K>> return
B =
1
2
0
0
För att avsluta felsökningen kan man skriva dbquit och då slutar även M-filen
att köras.
Det här sättet att felsöka sina filer är väldigt användbart då man kan följa
hur variablerna förändras. Man kan även använda sig av kommandot who för
att se vilka variabler som existerar för tillfället.
Under fliken Editor finns det även debugger-verktyg som fungerar på liknande sätt som förklarats ovan. Skillnaden är att man istället sätter ut breakpoints
i sin kod genom att klicka till höger om radsnumret i M-filen. Därefter kan man
använda sig av knapparna under fliken Editor, så som contiue, step, step in, run
to cursor och quit debugging.
Vilket av alternativet man väljer att använda är upp till användaren. Det
enklaste sättet att motverka logiska fel är såklart att koda på ett förebyggnade
sätt genom att t.ex. testa koden kontinuerligt. Fler tips finns i appendix C Tips
och Trix.
C
APPENDIX: TIPS OCH TRIX
C
93
Appendix: Tips och Trix
Desto mer man jobbar med MATLAB desto bättre blir man såklart, men i
början kan det vara bra med lite tips och trix. I det här kapitlet kommer vi först
lista en massa småtips som man borde försöka att alltid följa. I början av sin
MATLAB-karriär kan det vara bra att kolla igenom den med jämna mellanrum
så man ser att man fått med allt. Men ni kommer att inse efter ett tag att det
mesta kommer naturligt då man känner sig mer bekväm med MATLAB, då
behöver ni inte småtipsen längre.
De andra delkapitlen i detta appendix handlar om sådant man kanske inte
behöver kunna men som kan vara bra att veta att det finns utifall man känner
att man vill använda det. Så ett tips är att läsa igenom dessa delkapitel och
komma tillbaka när det känns som att det finns en användning av något. För
att det som står i dessa kapitel ska vara användbara krävs det att läsaren själv
testar kommandona och lär känna dess för- och nackdelar. Det som står här är
endast inspiration, använd help och MathWorks för mer utförlig information.
C.1
Småtips att alltid följa
Här nedan kommer en massa småtips att listas som är bra att alltid ha för vana
att använda sig utav.
Indentering: MATLAB kräver inte att man indenterar sin kod för att den
ska kunna köras. Men det ger en bättre översikt, gör koden enklare för andra
att läsa och med en korrekt indentering är det lättare att upptäcka fel.
För att indentera hela sin kod på en gång kan man om man sitter i Windows
använda sig av smart indent genom att markera hela filen och trycka ctrl+I.
Om detta inte fungerar borde det fungera om man under Home → Preferences
ändrar till Windows Default Set under Active settings. Denna ändring kan man
även göra om man sitter på andra operativsystem. En annan bra inställning
man kan göra är att under Home → Preferences under Indenting klicka i rutan
Apply smart indenting while typing. Det som händer då är att koden man skriver
indenteras automatiskt när man skriver t.ex. loopar där det är uppenbart att
nästa rad ska indenteras.
Kommentarer: Kommentera alltid koden. Man glömmer fortare än vad man
vill erkänna och om man vill att någon annan ska kunna läsa och förstå koden
är kommentarer ett måste. I större program är det oftast mer än en programmerare som jobbar med samma arbete och då är det av största vikt att koden
är kommenterad. Att veta hur mycket man ska kommentera och hur tydligt är
alltid svårt innan man fått en känsla för vad som är lagom. Man kanske inte behöver kommentera varje loop t.ex. men det är bättre att kommentera för
mycket än för lite om man är osäker. Man kan ha som regel att kommentera
vad alla funktioner gör, dess inparametrar och returvärden, nya variabler, vad
en sekvens med kod gör, o.s.v. Överallt där det inte är helt uppenbart vad som
kommer att göras borde man kommentera.
I MATLAB görs kommentarer med % och all efterföljande text blir grön och
bortkommenterad. I Windows kan man kommentera bort ett helt stycke genom
att markera texten och trycka ctrl+R. Om man vill ta bort kommenteringen
C
APPENDIX: TIPS OCH TRIX
94
markerar man texten, trycker ctrl+T och får tillbaka koden. Notera att detta
gäller då man har angett Windows Default Set under Active settings.
Spara: Detta tips kan verka självklart men det händer rätt ofta att man inte
sparar sina filer med förklarande namn eller på smarta ställen. Ta för vana att
alltid spara undan sina filer med förklarande namn, man vet aldrig när man kan
behöva kolla upp hur man gjorde tidigare.
Namnge variabler smart: Att namnge sina variabler med förklarande innebörd gör även det att det är lättare för andra att förstå koden. Vad variabeln
g innehåller är väldigt svårt att förstå medan time förmodligen innehåller tiden. Att namnge sina variabler på liknande sätt genom hela koden ger även en
snyggare helhet.
Börja om/skriv om: Man ska inte vara rädd för att radera allt som man
precis skrivit och börja om. Ofta blir man blind av att stirra på en kod som inte
fungerar och då kan det vara bra att börja om helt. Även om koden fungerar kan
det vara bra att skriva om vissa delar för att optimera och förbättra koden. Kan
man skriva om sin kod så den inte använder massa loopar tjänar man massa
datorkraft.
M-filer: Att använda sig utav M-filer kan vara mycket användbart då man
vill köra en funktion som har många olika inparametrar. Istället för anropa
funktionen i kommandofönstret och behöva komma ihåg i vilken ordning man
ska ange inparametrarna kan det vara smart med en M-fil där man sparar alla
inparameterar och dess värden och sen kallar på funktionen. Om man vill ändra
en inparameter kan man enkelt göra det och sen köra M-filen igen.
M-filer är även användbart om man läser in data från filer för att sedan
plotta resultaten. Om datafilen ändras kan man få nya plottar bara genom att
köra samma M-fil igen fast med en förändrad textfil.
Testa koden kontinuerligt: Ju större program man programmerar desto
viktigare är det att testa sin kod kontinuerligt. När man är ovan att jobba med
vektorer och matriser kan det t.ex. vara bra att hela tiden testa om de skapas
på det sätt man tänkt sig. Ett vanligt fel är att man blandar ihop rader och
kolumner vilket man enkelt kan undersöka med kommandot size. Efter varje
ny funktion eller loop borde man också undersöka om man får det resultatet
som man har tänkt sig. Att sitta med en kod på flera hundra rader och inse
att slutresultatet inte stämmer gör det svårt att hitta vart man gjort fel. När
MATLAB inte klagar på det man skrivit men ändå inte gör som man menar
uppstår de svåraste felen. Dessa är helt omöjliga att upptäcka om man inte
testar sin kod kontinuerligt. Tiden det tar att testa varje ny del i koden direkt
sparar man flera tusen gånger om i jämförelse med att försöka hitta felen i
efterhand.
Utskrifter: För att testa sin kod, både när man vill se om den fungerar eller
för att hitta fel, är det ett bra första sätt att använda sig utav utskrifter som
man sedan tar bort. Utskrifterna hjälper till att visa vart en variabel ändras till
C
APPENDIX: TIPS OCH TRIX
95
ett värde som verkar ologiskt. Man kan sedan gå bakåt i koden för att hitta vart
felet uppstår.
Dölj kodstycken: Ibland när man har långa koder som man arbetar med kan
det vara bra att dölja saker som man inte använder just då. T.ex. loopar som
man vet fungerar. Det kan man göra genom att trycka på det lilla minustecknet
till vänster om loopen så döljs allt utom den översta raden följt av punkter.
För att sedan kunna se loopen igen kan man trycka på plustecknet som skapats
istället för minustecknet. Om man vill dölja eller visa all kod kan man göra det
genom att högerklicka någonstans i koden och sedan trycka Code folding följt
av Fold all respektive Expand all.
Kör koden i sektioner: Att dela upp sin kod i sektioner kan vara användbart
om man vill göra samma saker flera gånger men kanske för olika funktioner eller
att man vill köra bara delar av sin kod. Att dela upp sin kod i sektioner gör
man genom att skriva %%. MATLAB skapar då en sektion, eller cell, i koden.
För att bara köra sektionen kan man trycka på Run section under fliken Editor
eller trycka ctrl+Enter. När man skapat sektioner kan man köra hela sin kod
som vanligt genom att tryck Run under fliken Editor eller trycka F5.
Avbryta oändliga loopar: Ibland råkar man skapa oändliga loopar, alltså
loopar som aldrig kommer bli färdiga. För att avbryta en sådan körning kan
man trycka crtl+C. MATLAB kommer då skriva ut Operation terminated
by user during exempel (line3), om man kör en fil med namnet exempel.
Allokering: Att allokera minne för sina vektorer och matriser sparar datorkraft, vilket är något som man alltid ska sträva efter att göra. Hur man allokerar
finns att läsa under avsnitt 2.2.
Clear all, close all: Något man alltid bör skriva överst i sina M-filer är
close all och clear all, så slipper man bli förvirrad av resultat från tidigare körningar. close all stänger alla figurfönster och clear all raderar
alla tidigare variabler. Att skriva detta överst i sina M-filer gör att man alltid
nollställer MATLAB på samma sätt som om man hade startat om programmet.
Humörhöjande: Om det går extra tungt en dag framför MATLAB är det
dags att prova på nya kommandon. Testa t.ex. spy, why,
load train följt av sound(y,Fs) eller varför inte testa att plotta detta:
x=[−2:.001:2];
y=(sqrt(cos(x)).*cos(200*x)+sqrt(abs(x))−0.7).*(4−x.*x).ˆ0.01;
plot(x,y)
C.2
Publish
I MATLAB finns det ett kommando som heter publish som man kan använda
om man vill publicera sin kod på ett snyggt sätt, vilket kan vara användbart då
man t.ex. föreläser eller ska redovisa en uppgift. Kommandot publish sparar
C
APPENDIX: TIPS OCH TRIX
96
kod, kommentarer och resultat som en html-fil. För att publicera sin kod kan
man under fliken Publish trycka publish. Då sparas html-filen i en mapp som
skapas i samma mapp som sin M-fil ligger i. En fördel med att publicera sin kod
jämfört med att bara kopiera koden är att med publish skapas även figurer i
den publicerade filen. Om man vill skapa en pdf istället kan man använda sig
av samma kommando i kommandofönstret och lägga till valet 'pdf':
publish('publishmaterial.m', 'pdf')
Detta kommando kan man göra med alla sina M-filer men det finns trick
som gör den sparade filen snyggare, t.ex kan man använda sig av dubbla % för
att skapa rubriker. Nedan visas en exempelkod som skapats för att demonstrera
publish, kopiera och testa för att se hur den publicerade filen ser ut.
%% Publish MATLAB−filer
% This is a M−file made in order to demonstrate the MATLAB command publish.
% In order to demonstrate that a sine−function is plotted.
%% Create vectors and plot it
t = 0:.1:pi*4;
func = sin(t);
plot(t, func)
hold on
%% Add lines in the figure
% In each iteration a new line is added into the figure and displayed
% togheter with the value of k.
for k =0:2
%%
%A new line with the slope k.
disp('k = '), disp(k)
plot(t, k*t, 'r')
end
C.3
Multi-dimensionella matriser
I avsnitt 2.1.2, om matriser, har vi tidigare nämnt att man kan skapa matriser
med flera dimensioner. Detta kan man göra på samma sätt som när man skapar
vanliga matriser men man anger tre dimensioner när matrisen skapas:
>> temperature=zeros(3,3,3)
temperature(:,:,1) =
0
0
0
0
0
0
0
0
0
temperature(:,:,2) =
0
0
0
0
0
0
0
0
0
C
APPENDIX: TIPS OCH TRIX
97
temperature(:,:,3) =
0
0
0
0
0
0
0
0
0
Fler-dimensionella matriser kan t.ex. vara bra att använda då man vill spara
temperaturen i ett rätblock eller spara saker i två dimensioner som ändras med
tiden. I ovanstående exempel skrivs temperaturerna ut ”blad för blad”. Med tre
dimensioner kan man tänka sig att det första indexet representerar x, det andra
y och det tredje z. Notera att det är väldigt enkelt att det blir dimensionsfel
då man försöker utföra operationer på fler-dimensionella matriser. Det gäller
att vara noggrann och hålla koll på vad man gör när man arbetar med flerdimensionella matriser.
C.4
Cell-arrayer
Om man vill spara olika sorters data i samma datatyp kan man använda sig
av cell-arrayer. Cell-arrayer innehåller antingen textsträngar, kombinationer av
text och siffror eller matriser med siffror med olika längder. För att skapa cellarrayer används kommandot cell:
>> C = cell(2,3)
C =
[]
[]
[]
[]
[]
[]
Med kommandot cell skapas en tom cell-array. Enkelt sett kan man se en
cell-array som en matris med matriser på varje index. För att ändra värden i
cell-arrayen används måsvingar:
>> C(1,1:3)
= {'one', 'two', 'three'};
>> C(2,1:3)
= {1,2,3};
C =
'one'
[ 1]
'two'
[ 2]
'three'
[
3]
Man kan även lägga till en ny matris på ett specifikt index:
>> C(2,1) = {[1,2,3]}
C =
'one'
[1x3 double]
'two'
[ 2]
'three'
[
3]
Cell-arrayer kan vara användbara om man behöver spara olika sorters data som
hör ihop. T.ex namn på personer som en textsträng tillsammans med åldern
som är ett tal.
C
APPENDIX: TIPS OCH TRIX
C.5
98
Struct
Ett annat sätt, förutom cell-arrayer, att spara data på av olika typer är att
använda sig av struktar. Dom fungerar på ungefär samma sätt men istället för
index för att komma åt datat används namn. Säg att vi vill spara information
om studenter, t.ex. vad dom heter och vilket år dom går. Då kan man skapa en
strukt med kommandot struct:
>> student = struct('Name', 'Kajsa', 'Year', 3)
student =
Name: 'Kajsa'
Year: 3
>> student.Name
ans =
Kajsa
Här har vi skapat en student med namnet Kajsa som går tredje året. Vill vi
lägga till en person i vår strukt måste vi använda index:
>> student(2) = struct('Name', 'Kalle', 'Year', 2)
student =
1x2 struct array with fields:
Name
Year
Nu skrivs inte namnet och årskursen ut eftersom den inte vet vems namn eller
årskurs den ska skriva. Istället får man information om vilken information som
lagras i strukten student, i detta fall Name och Year. Vill man skriva ut något
får man igen använda index:
>> student(2)
ans =
Name: 'Kalle'
Year: 2
Man kan även välja att lägga till studenter där man inte har all information,
t.ex. om man inte vet vilken klass Sara går i:
>> student(3).Name = 'Sara';
>> student(3)
ans =
Name: 'Sara'
Year: []