Efter laborationen ska du
Laborationen avslutas med en temauppgift, där du får träna på att konstruera script i Matlab.
Logga in på datorn och starta Matlab. På LTH:s Linux-datorer klickar du på Ubuntu-ikonen, som finns överst till vänster på skärmen (och ser ut som bilden här till höger). Skriv matlab och tryck Return.
På samma Linux-datorer kan du enkelt få dina två fönster (Matlab + denna webbläsare) sida vid sida. Klicka och dra i Matlab-fönstrets titelrad, och dra fönstret till skärmens kant (vänster eller höger). När du ser en "skugga" över halva skärmen släpper du fönstret där. Gör därefter likadant för webbläsaren, fast dra den istället till den andra kanten.
Gör några enkla beräkningar (de vanliga räknesätten) i kommandofönstret (Command Window) och prova att använda variabler.
Med Matlab kan man enkelt hantera såväl reella som komplexa tal.
Skriv ut följande värden:
Komplexa tal presenteras alltså i rektangulär form (det vill säga med real- och imaginärdel). Ibland är man istället intresserad av talets polära form (absolutbelopp och argument).
Tilldela variabeln z något av de komplexa värdena i uppgift D2(c)-(e) ovan. Skriv ut absolutbelopp och argument för z.
arg(z)?Funktionen angle(z) ger argumentet (vinkeln) för ett komplext tal z.
Tilldela z ett annat av de tre komplexa värdena och skriv ut real- och imaginärdel för z.
Ofta är det praktiskt att spara en sekvens av kommandon i en fil. Då har man kommandona sparade till senare, och kan man köra dem tillsammans igen. Sådana script är alltså ett slags små program.
Klicka på New→Script (se bilden ovan). Ett nytt delfönster dyker upp med ett script som än så länge heter "untitled". Skriv in följande text, klicka på Save-knappen och spara scriptet som lab1.m. Låt scriptet förbli öppet – du kommer att bygga vidare på det.
Den första raden är en rubrik. I nästa uppgift kommer du att få se hur sådana rubriker används.
Notera att scriptet lab1.m nu återfinns bland dina Matlab-filer i delfönstret Current Folder. Därifrån kan du öppna det senare om du vill. Det finns kvar även efter du stängt Matlab.
Klicka på Run. Alla tre satserna i ditt script körs, men du kan bara se resultatet från en av dem. Vilken? Varför?
Du kan även köra samma script genom att ange dess namn i kommandofönstret. Skriv lab1 i kommandofönstret och kontrollera att du får samma svar.
Alla tre variablerna är definierade i Matlab, även om bara en är utskriven. Pröva gärna följande i kommandofönstret:
Här har det du ska skriva in markerats i fetstil (b). Den övriga texten är det förväntade resultatet från Matlab.
Inför de följande uppgifterna ska du skapa ett nytt avsnitt i ditt script.
Lägg till en rad med två procenttecken och en rubrik sist i ditt script, exempelvis så här:
En sådan rad som inleds med två procenttecken (%%) markerar början på ett nytt avsnitt i scriptet. Detta avsnitt kan köras separat, utan att man behöver köra hela scriptet på en gång. Då använder man knappen Run Section, som du finner strax till höger om Run-knappen (se bilden nedan).
Placera textmarkören i scriptets första avsnitt (Komplexa tal) och tryck på Run Section. Kontrollera att samma sak som i förra uppgiften sker.
Placera därefter markören i scriptets andra avsnitt (Funktioner) och tryck på Run Section. Nu händer ingenting, eftersom detta avsnitt än så länge är tomt.
Låt oss definiera funktionen gx som följer:
Definiera gx i ditt script. Gör definitionen på en enda rad med en s.k. anonym funktion, så som beskrivs i Matlab Primer.
Glöm inte köra script-avsnittet med funktionsdefinitionen.
Kontrollera (i kommandofönstret) att funktionen ger rätt resultat:
Om något inte stämmer, justera ditt script och tryck Run Section igen.
Vi är nu intresserade av funktionens värden i intervallet 0 ≤ x ≤ 10.
Lägg till en rad i ditt script, där en vektor av 100 sådana x-värden skapas, jämnt fördelade.
Kontrollera (i kommandofönstret) att värdena verkar rimliga:
Undersök Matlabs Workspace-delfönster. Om du inte ser något sådant delfönster kan du öppna det genom att klicka på knappen Layout och välja Workspace (under rubriken Show).
I Workspace-fönstret ser du vilka variabler Matlab känner till just nu, och vilka värden de har.
Vilken information om x kan du få ur Workspace-fönstret? Är x en rad- eller kolonnvektor? Hur många element har den? Kan du se funktionen du definierade ovan?
Nu vill vi beräkna värdet av funktionen g för alla dessa x-värden.
Lägg till en rad i ditt script, så att en motsvarande vektor y av funktionsvärden skapas.
I Matlab Primer finns ett exempel där en serie funktionsvärden beräknas. Kan du komma på hur du kan använda samma teknik här?
Du kan behöva justera din funktion så att den använder elementvisa operationer.
Kontrollera att även dessa värden verkar stämma:
I det senare kommandot är x(27) värdet av element 27 i vektorn x, och det värdet används i sin tur som parameter till funktionen g. Resultatet ska överensstämma med element 27 i vektorn y.
Låt ditt script plotta funktionen (gx enligt ovan) för värdena 0 ≤ x ≤ 10.
Ditt Funktioner-avsnitt ska nu se ut i stil med följande (fast du ersatt ... med något annat):
I fortsättningen kan du själv välja när du vill skapa nya avsnitt i ditt script. Du kan också själv välja vilka kommandon du skriver i ditt script, och vilka du skriver direkt i kommandofönstret. Fråga gärna handledaren om du är osäker.
Matlab och Java är två olika programspråk för lite olika ändamål: Matlab är inriktat på små program av numerisk/matematisk karaktär, och Java är inriktat på större program och generellare tillämpningar. De två språken har både likheter och skillnader.
Matlabs funktioner motsvaras i Java närmast av metoder, även om det finns viktiga skillnader. I Java finns även vektorer, som liknar Matlabs vektorer på många sätt. (Om du läser F, I eller Pi har du nog ännu inte kommit i kontakt med Java-vektorer, men det kommer du snart att göra.)
Matlab använder samma syntax till både funktioner och vektorer, trots vi här ser dem som två ganska olika saker. I förra uppgiften skrev vi g(0), och då är g en funktion och 0 ett parametervärde. Här skriver vi x(1), där x är en vektor och 1 ett index. Vad ett uttryck som a(3) betyder beror alltså på om a är en funktion eller en vektor.
I Java skrivs dessa två saker olika: ett metodanrop inom klassen kan exempelvis skrivas g(0), medan en vektor indexeras med klamrar, exempelvis x[1]. I Java indexeras vektorer dessutom från 0, medan Matlab indexerar dem från 1.
Ibland vill man (approximativt) beräkna derivatan för en given funktion. Då kan man utgå från derivatans definition:
I analysen låter man ju h gå mot noll. Här måste vi bestämma oss för ett värde, och låter därför istället h vara ett "lagom" litet tal. Vi kan exempelvis sätta h till 10–6:
Definiera en funktion deriv som tar två parametrar: en funktion f, och ett x-värde. Funktionen deriv(f,x) ska beräkna (approximera) f'x enligt ovan.
Du definierar funktionen med något i stil med
där den saknade delen (...) hämtas från derivatans definition ovan. Parametern f är en funktion, och x är ett x-värde vi vill beräkna derivatan för.
Derivatans definition kan skrivas i Matlab som
Använd en funktion med känd derivata för att testa din deriv-funktion för något x-värde. Hur nära kommer approximationen?
Vi vet ju exempelvis att derivatan av sin x är cos x. När du anger sin som parameter i Matlab måste du skriva @sin (se Matlab Primer, "Function Handles").
Vad ger följande kommandon för resultat? Är resultaten rimliga?
Ett annat sätt att övertyga sig om att deriv ger rimliga resultat är att plotta en funktion tillsammans med sin (approximerade) derivata. Här kan vi göra detta för funktionen g(x) i uppgift D6.
Plotta gx och g'x i samma diagram, för 0 ≤ x ≤ 10. Använd deriv för att approximera g'x, och gör grafen för g'x röd.
Tips om hur du väljer färg hittar du i Matlab Primer, "Specifying Line Styles and Colors".
För att få flera grafer i samma bild kan man skriva hold on efter man gjort den första grafen. När man sedan gör nästa graf ritas den tillsammans med den första, istället för att ersätta den.
Verkar den approximerade derivatan rimlig?
Derivatan ska exempelvis vara noll vid funktionens lokala maxima/minima. Derivatan ska i sin tur ha ett lokalt maximum då funktionen växer som brantast.
För att se axlarna tydligare kan du använda axis on.
Behåll fönstret med graferna öppet. Vi ska nu se hur man kan utrusta det med rubriker och spara bilden som en fil.
Lägg till följande rader i ditt script, och notera hur fönstret med graferna förändras:
Det sista kommandot ovan skapade en fil som heter funktionsbild.png och hamnat bland dina Matlab-filer (se i delfönstret Current Folder). Sådana png-bilder kan importeras i ett ordbehandlingsprogram (LaTeX, Word eller något annat) och användas i exempelvis en labbrapport.
Bent, Alva och Kit försöker derivera funktionen gx ovan analytiskt. Det är länge sedan de läste analys, och endast ett vagt minne av deriveringsreglerna återstår. De kommer fram till olika svar.
Vi ska nu använda Matlab för att försöka jämföra dessa tre kurvor h1x, h2x och h3x med din beräknade derivata deriv(g,x). Du ska alltså inte använda dina kunskaper om deriveringsreglerna för den här uppgiften.
Skapa fyra vektorer av derivatavärden: en från deriv(g,x), en från h1x, en från h2x och en från h3x.
Skapa tre nya vektorer, en för var och en av de tre funktionerna. Varje vektor ska innehålla differenserna mellan funktionens värden och den beräknade derivatans.
Varje vektor anger alltså hur mycket respektive funktion avviker från den "riktiga" (beräknade) derivatan.
Med beteckningarna från föregående ledtråd blir
Vi har nu tre differensvektorer, en för varje funktion. De är rätt jobbigt att läsa igenom och jämföra tre vektorer om hundra element. Istället vill vi ha ett enda mått på respektive differensvektors storlek.
Här är funktionen norm, som beräknar en vektors magnitud (euklidisk norm), användbar. Den är ett enkelt och bra storleksmått på en vektor. Läs gärna om den euklidiska normen på Wikipedia, eller pröva help norm.
Vilken av de tre funktionerna kan anses ligga närmst den beräknade derivatan?
Med beteckningarna från föregående ledtråd kan man göra
norm betyder att vektorn innehåller små värden. En av normerna ligger nära noll, och motsvarar alltså den korrekta derivatan. Vi söker en matris med följande utseende:
Bilda matrisen M ovan med hjälp av Matlab-funktionerna eye och ones.
Ovan till höger finns en knapp []. Om du trycker på den så genereras en ny uppgift. Pröva!
Betrakta följande ekvationssystem (med tre obekanta , och ):
Lös ekvationssystemet genom att skriva om det på matrisform och använda operatorn "\".
Ekvationssystem på matrisform beskrivs i Matlab Primer, avsnitt 3.
Ekvationssystemet kan skrivas A·xb, där
Med dessa beteckningar söker vi kolonnvektorn x.
Kontrollera att din lösning uppfyller ekvationerna. Även det kan göras enkelt i Matlab — hur då?
På matrisform skriver vi ju A·xb, där x är lösningen du fann ovan. Med dessa beteckningar ska både vänsterledet A*x och högerledet b ska ha samma värde.
Kontrollera detta genom att skriva ut dessa båda värden i Matlab.
Betrakta matrisen A nedan:
| 1 | 1 | –1 |
| 2 | 1 | 1 |
| 4 | 3 | –1 |
Bestäm determinanten för A. Använd en av Matlabs inbyggda funktioner.
Determinanter behandlas i kursen i linjär algebra, som du kanske ännu inte läst. Det är inget bekymmer här.
Determinanten är ett värde som man kan beräkna för en given matris, och som säger oss något om matrisens egenskaper. Exempelvis är det intressant, visar det sig, att veta huruvida matrisens determinant är noll eller ej.
En bra gissning är att funktionens namn påminner om "determinant". Pröva att söka efter "determinant" i Matlab Primer.
Om matrisen heter exempelvis A kan man skriva
Använd Matlab för att lösa följande ekvationssystem:
Du får sannolikt fram ett märkligt felmeddelande, och värdena i resultatet ser nog också konstiga ut. Hur ska man tolka detta? Jämför med matrisen A ovan.
I kursboken i linjär algebra kan man läsa följande:
Huvudsatsen. För kvadratiska matriser A är följande villkor ekvivalenta:
Ur: Gunnar Sparr, Linjär algebra, andra upplagan, Studentlitteratur 1995, s. 212.
Ekvationssystemet saknar lösning (vilket också indikeras av att determinanten är noll).
Du har redan sett att Matlab kan användas för att beräkna kvadratrötter, till och med komplexa sådana. Och i Java kan vi naturligtvis använda Math.sqrt(x) för att få fram roten ur reella x. Här ska vi titta närmare på hur en sådan beräkning kan fungera.
Kvadratroten av ett positivt, reellt tal S kan beräknas iterativt så här (mer om algoritmen nedan):
Här beräknas alltså successivt allt bättre approximationer xk+1 till √S, hela tiden utifrån den föregående approximationen xk. Med "tillräckligt" många upprepningar får vi en approximation av √S. Som startvärde kan vi exempelvis gissa
Skriv ett Matlab-script som läser in ett tal S från tangentbordet, och därefter skriver ut de tio första approximationerna av √S med algoritmen ovan.
Använd gärna knappen New→Script för att komma igång.
Ditt script ska inte använda sig av Matlabs sqrt-funktion.
Kontrollera att ditt script fungerar, exempelvis genom att jämföra med exemplet ovan.
Som du kanske ser konvergerar beräkningen ganska fort. Det är sällan nödvändigt med tio iterationer, men det är svårt att på förhand avgöra exakt hur många som behövs.
Ändra ditt script så att det inte gör ett fixt antal iterationer (tio ovan), utan beräknar nya värden tills serien konvergerar. Låt scriptet skriva ut antalet iterationer som behövdes.
Använd följande kriterium för konvergens:
Tips: Om ditt program fastnar i en oändlig loop kan du bryta det genom att klicka i kommandofönstret och trycka Ctrl-C.
Du behöver två x-värden för iterationen: en variabel för nuvarande x-värde, och en för det föregående. Välj deras startvärden på ett sådant sätt att while-satsen inte avbryts från början.
Du använde Matlabs funktion för absolutbelopp i en av laborationens första uppgifter.
Om ditt script inte verkar konvergera, utan fastnar i en oändlig loop, fundera då på ditt while-villkor.
Lägg in en ny rad i din loop, där båda variablerna skrivs ut (om variablerna exempelvis heter x1 och x2):
Här ska de första raderna vara olika, men efter några iterationer ska de två värdena bli lika. Om värdena är helt lika redan från början så behöver du titta närmare på i vilken ordning dina variabler får sina värden. Hur ska du göra för att komma ihåg både det nuvarande och det förra värdet?
< eller > i ditt while-villkor? Vilket ska villkoret vara för att loopen ska fortsätta?Tips: När man skriver Matlab-script kan det vara praktiskt att inleda med en serie kommandon som återställer Matlab till ett känt ursprungsläge. Exempelvis kan man inleda sitt script med följande kommandon:
Pröva gärna att stoppa in kommandona ovan i ditt kvadratrotsscript och se att de fungerar som du förväntar dig.
När du kommit hit är du klar med den första Matlab-laborationen. Läs igenom uppgifterna igen och se till att du förstår dina lösningar inför redovisningen.
Approximationstekniken ovan användes av babylonierna (i nuvarande Irak) kring 1600–1800 f.Kr., även om de naturligtvis inte använde samma symboler som oss. De använde ett positionsbaserat talsystem baserat på basen 60, och alltsedan dess delar vi upp timmar i 60 minuter, och minuter i 60 sekunder. Och de hade alltså även en metod för att beräkna kvadratrötter.
Det är inte helt klart om babylonierna gjorde mer än en iteration i sina kvadrotsberäkningar, men vi vet att de kände till approximationen ovan. De kände också till √2 med en noggrannhet motsvarande ungefär sex decimaler. I alla händelser beskrev Heron (ca 10–70 e.Kr.), verksam i Alexandria i nuvarande Egypten, den iterativa algoritmen ovan. Idag kan vi även komma fram till samma algoritm om vi utgår från Newton-Raphsons metod. Då ser vi problemet som att söka nollställen till funktionen
Persondatorer har idag ofta en särskild instruktion för kvadratrotsberäkning, men även sådan hårdvara använder en iterativ algoritm av ovanstående typ. I många tekniska tillämpningar använder man dessutom enklare processorer, som saknar sådana instruktioner. Då kan man beräkna kvadratrötter på det sätt som du prövat här, precis som babylonierna gjorde för närmare fyratusen år sedan.