1 Matlab: problemen oplossen binnen de lineaire algebra

advertisement
1
Matlab: problemen oplossen binnen de lineaire algebra
We beginnen met enkele eenvoudige voorbeelden van hoe je in Matlab lineaire algebra kunt
doen. Dit verschaft een eerste uitvalsbasis om binnen Matlab te kunnen gaan experimenteren.
1.1
Matlab als rekenmachine, scalaire variabelen
Voorbeeld van een concrete numerieke berekening in Matlab is
>> (5+2)*3+2^3-1
ans =
28
Matlab bevat de meeste voor de hand liggende standaardfuncties, zoals
sin, cos, tan, exp, log, sqrt, abs, sign, round, ceil, floor
met als voorbeeld de volgende berekening en antwoord
>> sin(2)^2+cos(2)^2-1+exp(1)
ans =
2.7183
Matlab rekent standaard in 16 decimalen; wil je deze allemaal zien, dan kan dat als volgt
>> format long
>> pi
ans =
3.14159265358979
Belangrijk is dus om je te realiseren dat Matlab doorgaans geen exacte antwoorden geeft. Zie:
>> sin(pi)
ans =
1.224646799147353e-016
Zoals in iedere programmeertaal kan je waarden toekennen aan variabelen en daarmee rekenen,
>> a=2; b=3; c=a*b-1
c =
5
1
>> c*a
ans =
10
Je ziet dat als je een commando afsluit met een punt-komma, het commando weliswaar wordt
uitgevoerd, maar dat de resultaten ervan niet op het scherm worden getoond.
Variabelen blijven beschikbaar tot je ze verandert of met clear expliciet leegmaakt.
>> b
b =
3
>> clear b
>> b
??? Undefined function or variable ’b’.
1.2
Vectoren, matrices, en eenvoudige lineaire algebra
Matrices en vectoren maak je tussen vierkante haken, met punt-komma’s om de rijen te
scheiden. Adjungeren (indien reëel, dan transponeren) gaat middels een navolgende apostrofe.
>> v = [1 2 3]
v =
1
2
3
>> w = v’
w =
1
2
3
>> A=w*v
A =
1
2
3
2
4
6
3
6
9
Deze rang-1 matrix kan je overigens ook direct definiëren middels
2
>> A=[1 2 3; 2 4 6; 3 6 9];
Matlab bevat veel handige commando’s in de context van lineaire algebra, zoals
max, min, mean, length, sum, prod,
null, rank, det, trace, inv, eig, schur,
jordan
met als voorbeelden
>> max(v)
ans = 3
>> length(w)
ans = 3
>> max(A)
ans =
3
6
9
waarbij max(A) het maximum in iedere kolom van A geeft. Als je het maximum van alle
entries van A wilt weten, moet je dus max(max(A)) gebruiken. De afmetingen van een matrix
en zijn rang vind je middels
>> size(A)
ans =
3
3
>> rank(A)
ans = 1
Merk op dat de rang van A inderdaad gelijk is aan 1, maar dat minieme afrondfouten deze rang
onmiddellijk verstoren. Wees heel voorzichtig bij het interpreteren van berekende resultaten
van grootheden die niet continu zijn in de entries van de matrix, zoals ook de Jordanvorm:
>> jordan([ 1 sin(pi); 0 1])
ans =
1
0
1
1
Het moge duidelijk zijn dat de correcte Jordanvorm van deze matrix de identiteit is.
In de context van eigenwaarden geven we de volgende voorbeelden,
3
>> d = det(A)
d =
0
>> lambda = eig(A)
lambda =
-0.00000000000000
-0.00000000000000
14.00000000000000
>> Q = null(A)
Q =
-0.89577591657327
-0.16887681694581
0.41117651682163
0.35518577654341
-0.82811009834681
0.43367814005007
waarbij de kolommen van Q een orthonormale basis van de kern van A vormen. Matlab geeft
doorgaans orthonormale basisses van deelruimtes als antwoord, omdat deze nauwkeuriger
berekend kunnen worden dan niet-orthonormale basissen (zie het derdejaarsvak Numerieke
Lineaire Algebra). Dit geeft in het algemeen wel onplezierige getallen. Desgewenst kan je met
>> null(A,’r’)
ans =
-2
1
0
-3
0
1
een basis voor de nulruimte berekenen rechtstreeks vanuit de rijgereduceerde echelonvorm van
A, die je overigens kunt vinden middels
>> rref(A)
ans =
1
0
0
2
0
0
3
0
0
Veel van de commando’s hebben meerdere outputs, maar alleen als je er expliciet om vraagt.
Zo geeft
4
>> [a,b]=max([3 2 5 1 2])
a =
5
b =
3
niet alleen de maximale waarde a=5 uit de gegeven vector maar ook de index b=3 van de entry
(of soms entries) waar dit maximum in de vector staat.
Een ander voorbeeld is het berekenen van eigenwaarden en eigenvectoren middels
>> [V,Lambda] = eig(A)
V =
-0.45430147666286
0.80367128200137
-0.38434702911329
0.84981268340345
0.26153046624052
-0.45762453862817
0.26726124191242
0.53452248382485
0.80178372573727
0
0.00000000000000
0
0
0
14.00000000000000
Lambda =
-0.00000000000000
0
0
zowel de matrix V als de matrix Lambda van de eigendecompositie van A, als deze bestaat.
Ook schur en jordan hebben in principe twee outputs.
1.3
Matrices opbouwen en afbreken
Individuele matrix- en vectorentries kan je opvragen
>> A = [1 2 3 ; 4 5 6 ; 7 8 9]; A(2,3)
ans =
6
en ook wijzigen
>> A(2,3) = 0
A =
1
4
7
2
5
8
3
0
9
5
Ook kan je entries horend bij specifieke rijen en kolommen allemaal tegelijk opvragen
>> A([1 3],[2 3])
ans =
2
8
3
9
en tevens als volgt wijzigen
>>
A([1 3],[2 3]) = [-1 -1 ; -1 -1]
A =
1
4
7
-1
5
-1
-1
0
-1
mits je wel de dimensies van die blokken respecteert. Handige stenografie is hierbij de
dubbelepuntnotatie, bijvoorbeeld 1:5 is dezelfde vector als [1 2 3 4 5]. Daarnaast geeft
A(:,2) de tweede kolom van A en A(3,:) zijn derde rij.
Sommige matrices kan je genereren middels een ingebouwd commando, zie bijvoorbeeld
zeros, ones, eye, magic, diag, rand
waarvan eye(n) een n × n identiteitsmatrix geeft. Je kan met behulp van deze commando’s
matrices in blokken in elkaar zetten, bijvoorbeeld
>> A = [ones(2,2) zeros(2,3) ; 3*eye(3) 2*ones(3,2)]
A =
1
1
3
0
0
1
1
0
3
0
0
0
0
0
3
0
0
2
2
2
0
0
2
2
2
>> D = diag([1 2 3])
D =
1
0
0
0
2
0
0
0
3
>> diag(D)
6
ans =
1
2
3
Dus diag verandert een vector in een diagonaamatrix met die vector als diagonaal, en andersom: losgelaten op een matrix wordt de verticale vector van diagonaalentries geretourneerd.
Een belangrijke, nog niet genoemde matrix is de lege matrix [] die je kunt toekennen aan een
entry van een vector of een rij of kolom van een matrix, zoals bij dit magische vierkant
>> M = magic(4)
M =
16
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1
3
6
15
13
12
1
>> M(2,:) = []
M =
16
9
4
2
7
14
Nog net even ingewikkelder (maar vaak des te handiger) zijn de volgende mogelijkheden
>> x = [2 1 4 3 6 5 8 7];
>> y = [1 3 5 7];
>> x(y)
ans =
2
4
6
8
waarmee je dus de entries 1, 3, 5, 7 van x opvraagt. Met een soortgelijke constructie kan je
bijvoorbeeld de rijen (of kolommen) van een matrix permuteren
>> I = eye(5); z = [2 1 5 4 3];
>> I(z,:)
ans =
0
1
1
0
0
0
0
0
0
0
7
0
0
0
0
0
0
0
0
1
0
1
0
1
0
0
Tot slot noemen we nog de commando’s
rot90, fliplr, flipud
wat staat voor roteer 90 graden, flip-left-right en flip-up-down en die precies doen wat je denkt
dat die commando’s met matrices zullen doen, tenzij je wat anders dacht.
1.4
For, while, if, then
Net als iedere fatsoenlijke programmeertaal kan je in Matlab for-loops, while-loops en if-thenelse constructies gebruiken om je workflow van je programma te regelen.
De for-loop is een herhalingsstament. Een bepaalde taak wordt een vooraf gespecificeerde
hoeveelheid keren uitgevoerd, met mogelijkerwijs variabele parameterwaarden. Een heel eenvoudig voorbeeld is het volgende,
>> for j=1:5, v(j) = j^2; end
>> v
v =
1
4
9
16
25
Voor geavanceerde for-loops kan je gebruik maken van de regel dat de loopvariabele één voor
één de waarden aanneemt van de kolommen van de matrix die erachter staat. In bovenstaande
voorbeeld loopt j dus over de kolommen van de matrix 1:5, oftewel, over [1 2 3 4 5]. Een
voobeeld hiervan is
>> for e = eye(3), v = magic(3)*e, end
v =
8
3
4
v =
1
5
9
v =
6
7
2
8
waarin de loop-variabele de kolommen van de 3 × 3 identiteitsmatrix eye(3) doorloopt. De
output wordt dan de opeenvolgende kolommen van Matlab’s 3×3 magische vierkant magic(3).
De while-loop is ook een herhalingsstatement. Het verschil met een for-loop is dat je een
conditie gebruikt die aangeeft of er herhald moet worden. De volgende code is een voorbeeld.
>> j=0; while j^3+j^2+j+1 < 1000000, j = j+1; end
>> j
j =
47
Dit voorbeeld is intuı̈tief duidelijk: de variabele j wordt steeds met 1 verhoogd, zolang
j 3 + j 2 + j + 1 kleiner dan honderdduizend is. In dit geval kan je ook met de hand proberen
uit te rekenen dat j=47 de eerste waarde van j is waarvoor die uitdrukking niet meer kleiner
is dan honderdduizend, maar het gebeurt vaak genoeg dat je je in een situatie bevindt waarbij
je de conditie niet wil of kan berekenen en dan is een while-loop onontbeerlijk.
Even enkele woorden over condities in Matlab. Eerst een klein overzicht met veel voorkomende
condities, en commando’s om deze samen te stellen,
x < y,
x <= y,
x > y,
x >= y,
x == y,
x ~= y,
and,
or,
xor
Deze condities werken in Matlab ook op de volgende manier, waarbij de uitkomst 0 de waarheidwaarde false voorstelt, en 1 de waarheidswaarde true.
>> 2 < 3
ans =
1
>> 4 == 0
ans =
0
>> or((2 < 3),(4 == 0))
ans =
1
>> and((2 < 3),(4 == 0))
ans =
0
Synoniem voor or(a,b) is a | b en synoniem voor and(a,b) is a & b.
9
De logische contructen kunnen uiteraard ingezet worden bij het maken van conditionele statements. Voorbeelden van eenvoudige conditionele statements in Matlab zijn
>> k = 0; j = 1; if k == j, exit, end
Hierbij is exit het Matlab commando dat Matlab afsluit.
>> if 355/113 > pi, disp(’pi < 355/113’), else, disp(’pi > 355/113’), end
pi < 355/113
Met het disp-commando kan je je code mededelingen op het scherm laten schrijven.
Natuurlijk kan je ook, net als bij de while-loop, condities combineren,
>> if rem(j,2) == 0 & sqrt(j)==round(sqrt(j)), disp(’j: even kwadraat’), end
Om de output hiervan te zien moet j op dat moment natuurlijk wel een waarde hebben!
1.5
Een script-file voor Collatz-rijtjes
Het komt vaak voor dat je een experiment wilt herhalen met verschillende waardes van een
bepaalde parameter. In dat geval is het handig om de lijst van herhaaldelijk uit te voeren
commando’s op te slaan in een zogeheten script file. Dat is een Matlab-file met extensie “. m”.
Voorbeeld: We kiezen in het linksboven menu van Matlab de optie File −→ New M-File.
In deze file schrijven we de volgende tekst
n = 1;
while c(n) ~=1
if mod(c(n),2)==0
c(n+1) = c(n)/2;
else
c(n+1) = 3*c(n)+1;
end
n = n+1;
end
en we slaan de file op als collatz.m. In Matlab kunnen we nu het script aanroepen, ook wel
executeren genaamd. In deze script-file wordt voor een gegeven beginwaarde het Collatz-rijtje
gegenereerd. Collatz uitte het vermoeden dat de rij (cn )∞
n=1 gedefinieerd door cn+1 = cn /2
als cn even is, en cn+1 = 3cn + 1 als cn oneven is, voor iedere startwaarde c1 uiteindelijk in
de cykel 4 − 2 − 1 − 4 − 2 − 1 − . . . terecht komt.
Het commando mod(c(n),2) berekent de waarde c(n) modulo 2 en het conditionele statement
controleert dus of c(n) even is.
Voor startwaarde c=17 geeft dit het volgende resultaat.
>> c=17; collatz; c
c =
10
17
52
26
13
40
20
10
5
16
8
4
2
>> clear c; c=27; collatz; length(c), max(c)
ans =
112
ans =
9232
Dit voorbeeld laat zien dat het Colatz-rijtje voor c = 27 eerst flink grote waarden aanneemt,
en dat het 112 stappen doet alvorens in de periodieke cykel te belanden.
11
1
Download