Simuleringsberäkningar baserar sig oftast på stokastiska processer. Sådana beräkningar utförs med hjälp av slumptal, som i MATLAB genereras med funktionerna rand och randn. Kommandot x = rand (1000,1) kommer t.ex. att alstra en kolumnvektor med 1000 reella tal, som slumpmässigt valts ut ur intervallet (0, 1). Fördelningen är likformig, vilket innebär att om a, b är två godtyckliga tal som uppfyller villkoret 0 < a < b < 1, så kommer den bråkdel av de alstrade slumptalen, som ingår i intervallet [a, b] i medeltal att vara lika med intervallängden b − a. Funktionen randn används om man vill använda en normalfördelning. Som ett exempel skall vi se på ett program histo.m som använder rand och randn för att rita histogram med statistiska data: subplot(2,1,1) x = rand(1000,1); hist(x,30) axis([-1 2 0 60]) xlabel(sprintf(’Medeltal = %5.3f. Median = %5.3f.’,mean(x),median(x))) title(’Distribution av värden i rand(1000,1)’) subplot(2,1,2) x = randn(1000,1); hist(x,linspace(-3,3,100)) title(’Distribution av värden i randn(1000,1)’) xlabel(sprintf(’Medeltal = %5.3f. Standard deviation = %5.3f’,mean(x),std(x))) Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 1 Diagrammet nedan visar distributionerna: Som vi ser väljer rand värden likformigt från intervallet (0, 1), medan randn ger en normalfördelning. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 2 Histogramfunktionen hist kan användas på flere sätt. Kommandot hist(x,30) fördelar x-värden på 30 delintervall inom intervallet (0, 1). Man kan också specificera delintervallens positioner, såsom i det andra exemplet (hist(x, linspace(-3, 3, 100))). Programmet visar också hur man kan formatera figurtext med kommandot sprintf. Detta kommando har formen sprintf(formatsträng, variabellista), där formatsträngen anger hur texten skall skrivas ut. Formatet för varje variabel som ingår i variabellistan specificeras med en sträng, som börjar med ett procenttecken och efterföljs av ett decimaltal och en bokstav. %5.3f betyder t.ex. att 5 tecken reserveras totalt för variabeln, och 3 tecken för decimalerna. Bokstaven f anger flyttal, e anger exponentframställning. Ett heltal anges med 0 decimaler. Vi skall se på ett annat program scat.m, som genererar tvådimensionella spridningsdiagram av distributioner: p = rand(1000,2); subplot(1,2,1) plot(p(:,1),p(:,2),’.’) title(’Likformig fördelning’) axis([0 1 0 1]) axis(’square’) p = randn(1000,2); subplot(1,2,2) plot(p(:,1),p(:,2),’.’) title(’Normalfördelning’) axis([-3 3 -3 3]) axis(’square’) Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 3 Kommandot p = rand(1000,2) kommer här att alstra en 1000 × 2 matris av slumptal. Nedanstående bild visar diagrammens utseende: Man kan också konstruera slumptal med bestämda medeltal och standardavvikelser. Sålunda kommer t.ex. x=10 + 5*rand(n,1) att alstra likformigt fördelade slumptal inom intervallet (10, 15), och x=10 + 5*randn(n,1) alstrar normalfördelade slumptal med medeltalet 10 och standardavvikelsen 5. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 4 Slumptal har använts tidigt för matematiska beräkningar. Mycket känt är det berömda nålproblemet, som framlades av den franske biologen Georges Louis Leclerc (greve av Buffon) år 1773: Om en nål med längden l kastas slumpmässigt på ett papper, där man ritat linjer på konstant avstånd d från varandra (d > l), 2l så är sannolikheten för att nålen skall korsa en linje . Han ansåg därför att man kunde experimentellt πd bestämma π på detta sätt. År 1855 gjorde Ambrose Smith 3204 kastförsök med en stav enligt denna metod, och beräknade därur värdet på π till 3.1553. År 1901 lyckades den italienska matematikern Lazzarini efter 3408 nålkast (antalet lyckade var 1808) beräkna π med samma metod till 3.1415929, som skiljer sig först på sjunde decimalen från det korrekta värdet! Denna beräkning av π kan användas som en enkel illustration till Monte-Carlo metoden, en metod för att uppskatta integraler med hjälp av slumptal. Talet π kan uppfattas som ytan av enhetscirkeln. Antag att vi försöker ”träffa” en kvadrant i cirkeln i figuren nedan genom att konstruera slumptal, som har en likformig fördelning mellan 0 och 1. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 5 Man åstadkommer en serie ”träffar” i kvadraten OABC genom att välja två slumptal, konstruerade på det ovannämnda sättet, som får representera x- resp. y -koordinaten för en punkt i kvadraten. Avståndet från denna slumpmässiga punkt till origo beräknas. Om avståndet är mindre än 1, så har vi träffat det skuggade området, dvs innanför cirkeln. Om vi totalt skjuter n ”skott”, varav n1 träffar innanför cirkeln, så kan värdet av π uppskattas som π= 4 · ytan under kurvan CA 4n1 ≈ . ytan av kvadraten OABC n Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 6 √ Man kan visa att felet i uppskattningen av ytan är av storleksordningen 1/ n. Vi skall skriva ett MATLAB– program för att simulera ett dylikt experiment: clc figure rand(’seed’,142857) traff = 0; piupp = zeros(500,1); for k=1:500 x = -1+2*rand(100,1); y = -1+2*rand(100,1); traff = traff + sum(x.^2 + y.^2 <= 1); piupp(k) = (traff/(k*100))*4; end plot(piupp) title(sprintf(’Monte Carlo-uppskattning för pi = %5.3f’,piupp(500))); xlabel(’Antal försök per hundra’) Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 7 I början av programmet matas slumptalsgeneratorn med ett ’frö’ (142857), ett slumpmässigt heltal som används för att starta slumptalsberäkningarna. Sedan genereras två vektorer x och y, som innehåller 100 likformigt fördelade slumptal inom intervallet (−1, +1). Vi får alltså 100 punkter (x, y) innanför en kvadrat med sidan 2 och medelpunkt i origo. Av dessa punkter väljer man ut dem, som uppfyller villkoret x2 + y 2 ≤ 1 (dvs de punkter, som ligger innanför den inskrivna enhetscirkeln) och lagrar antalet av dem i variabeln traff (x.^2 + y.^2 <= 1 är ett logiskt uttryck, som då det är sant, har värdet 1, men värdet 0 i motsatt fall). Slutligen kan vi beräkna en uppskattning av π , då vi vet att förhållandet mellan cirkelns yta och kvadratens yta är π/4. Proceduren upprepas därpå 500 gånger. Resultatet av beräkningen visas i figuren nedan. Som vi ser, konvergerar uppskattningarna inte särskilt snabbt mot π . Vi kan därför konstatera, att nålkastningsexperimenten, som påstods ge nogranna värden av π , inte kan vara pålitliga. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 8 Ett annat exempel på användningen av slumptal är den brownska rörelsen. Den upptäcktes av den skotska botanikern Robert Brown 1827, då han med ett mikroskop undersökte pollenkorn suspenderade i vatten, och fann då en massa små partiklar, som oupphörligt rörde sig hit och dit, fullständigt oregelbundet. Han trodde först att det sammanhängde med växternas ”vitalitet”, men han upptäckte fenomenet också i vatten som varit inneslutet i kvarts under miljontals år, och insåg att den förklaringen måste uteslutas. Numera vet vi att den brownska rörelsen beror på, att vätskans molekyler sätter små dammpartiklar i rörelse, som kan observeras i mikroskopet (med mörkfältsbelysning). År 1905 skrev Einstein en artikel om den brownska rörelsen (utan att känna till dess förhistoria), som sedan ledde till hans doktorsavhandling. Det är ganska lätt att skriva ett Matlab–program, som simulerar Browns rörelse i två dimensioner, och ritar in den i ett koordinatsystem: Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 9 % brown.m simulerar den brownska rörelsen N=10000; % antal steg (= antalet punkter som räknas ut) t=100; h=t/N; % maximitiden=t, h=tidssteget x=zeros(N,1); % nollställ punkternas x-koordinater y=zeros(N,1); % nollställ punkternas y-koordinater x(1)=0.0; y(1)=0.0; % begynnelsepositionen for i=1:N % räkna ut N punkter x(i+1)=x(i)+sqrt(h)*randn; y(i+1)=y(i)+sqrt(h)*randn; end; plot(x,y); % rita ut punkterna grid on % lägg till ett rutnät Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 10 Kapitel 5. Introduktion till numeriska metoder MATLAB är ett utmärkt system om man vill bekanta sig med numeriska beräkningar, eftersom det gör det möjligt att experimentera med olika idéer, och genast se resultatet, t.ex. i form av en graf. Vi kommer här att beskriva enkla numeriska metoder på basen av materialet i C. Van Loan: Introduction to Scientific Computing. Vi skall börja med att studera noggrannhet vid beräkningar och talframställning i datorer. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 11 5.1. Fel och talframställning vid beräkningar Vid vetenskapliga beräkningar uppträder alla slags fel. Avrundningsfel förekommer i alla slags beräkningar, approximationsfel uppstår vid numerisk beräkning av derivator, mätfel förekommer i observationsdata, etc. Detta är något man inte kan undvika, och man bör därför vara medveten om det. Vi skall här koncentrera oss på approximationsfel och avrundningsfel. Om x̃ är en approximation för en skalär x, så är det absoluta felet |x̃−x| och det relativa felet |x̃−x|/|x|. Om det relativa felet är av storleksordningen 10−d, så har x̃ ungefär d korrekta signifikanta siffror, dvs det existerar ett tal : e = ±(. 00 . . . 0 nd+1nd+2 . . .) × 10 |d nollor {z } så att x̃ = x + (obs: exponenten e > 0). För att vi bättre skall förstå absoluta och relativa fel, skall vi se på ett exempel, nämligen Stirling– approximationen (eller, rättare sagt, en av dem) för fakultetsfunktionen: Sn = √ 2πn n n Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 e ≈ n! = 1 · 2 · · · n, JJ J I II × 12 där e betecknar det neperska talet 2, 718 . . .. Vi skriver en MATLAB-skript som gör en feltabell: % Stirling % % Prints a table showing error in Stirling’s formula for n! % close all clc home disp( ’ ’) disp(’ Stirling Absolute Relative’) disp(’ n n! Approximation Error Error’) disp(’----------------------------------------------------------------’) e=exp(1); nfact=1; for n=1:13 nfact = n*nfact; s = sqrt(2*pi*n)*((n/e)^n); abserror = abs(nfact - s); relerror = abserror/nfact; s1 = sprintf(’ %2.0f %10.0f %13.2f’,n,nfact,s); s2 = sprintf(’ %13.2f %5.2e’,abserror,relerror); disp([s1 s2]) end Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 13 I MATLAB-skripten visas också några nya exempel på formatering av utskrift. Kommandot disp (=display) används för att visa innehållet i en matris eller en textsträng (såsom ovan). Kommandot sprintf, som vi tidigare stött på, används här för att konstruera två strängvariabler s1 och s2, som konkateneras med kommandot disp([s1 s2]) (observera, att man också kan tolka strängar som radvektorer innehållande alfanumeriska tecken). Med konkatenering bildar man en ny längre radvektor från två kortare radvektorer. Kommandot clc tömmer kommandofönstret. Nedan visas den färdiga tabellen: Stirling Absolute Relative n n! Approximation Error Error ---------------------------------------------------------------1 1 0.92 0.08 7.79e-002 2 2 1.92 0.08 4.05e-002 3 6 5.84 0.16 2.73e-002 4 24 23.51 0.49 2.06e-002 5 120 118.02 1.98 1.65e-002 6 720 710.08 9.92 1.38e-002 7 5040 4980.40 59.60 1.18e-002 8 40320 39902.40 417.60 1.04e-002 9 362880 359536.87 3343.13 9.21e-003 10 3628800 3598695.62 30104.38 8.30e-003 11 39916800 39615625.05 301174.95 7.55e-003 12 479001600 475687486.47 3314113.53 6.92e-003 13 6227020800 6187239475.19 39781324.81 6.39e-003 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 14 Som vi ser, kommer det relativa felet att avta med växande n (Stirlings approximation är asymptotisk). Som ett annat exempel skall vi studera det relativa felet i exponentialfunktionens Taylor–utveckling, som kan uttryckas n xk x e = + Rn, k! k=0 X där resttermen Rn är eθx n+1 Rn = x , 0 < θ < 1. (n + 1)! Om man medtar ett ”tillräckligt” antal termer, kommer delsummorna att konvergera. Detta visas av nedanstående programskript, som ritar delsummornas relativa fel som funktion av n för olika värden av x. % Script File ExpTaylor % % Plots, as a function of n, the relative error in the % Taylor approximation % % 1 + x + x^2/2! +...+ x^n/n! % % to exp(x). close nTerms = 50; Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 15 for x=[10 5 1 -1 -5 -10] figure error = exp(x)*ones(nTerms,1); s = 1; term = 1; for k=1:50 term = x.*term/k; s = s+ term; error(k) = abs(error(k) - s); end; relerr = error/exp(x); semilogy(1:nTerms,relerr) ylabel(’Relative Error in Partial Sum.’) xlabel(’Order of Partial Sum.’) title(sprintf(’x = %5.2f’,x)) pause(3) end I detta program används en halvlogaritmisk framställning (kommandot semilogy) för att rita graferna. Detta är lämpligt i detta fall, eftersom det relativa felet varierar många dekader. Kommandot semilogy används på samma sätt som plot. Programmet alstrar sex bildfönster, ett för vart och ett av de sex värdena av x. Nedan visas två av dem, nämligen graferna för x = 1 och x = 10. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 16 Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 17 Som vi kan se, avtar felet i delsummorna snabbare för små värden av x än för stora. vilket man kunde vänta sig. Dessutom ser det som felet inte går exakt till noll, utan slutar att ändra sig då antalet termer har ökats tillräckligt. Dessa problem förstår vi bättre när vi lär känna flyttalsaritmetiken. Vi skall studera ett annat exempel, nämligen polynomet p(x) = (x − 1)6, som beräknas inom intervallet [1 − δ, 1 + δ] ur formeln p(x) = x6 − 6x5 + 15x4 − 20x3 + 15x2 − 6x + 1. MATLAB–programmet ser ut så här: % % % % % Script File Zoom Plots (x-1)^6 near x=1 with increasingly refined scale. Evaluation via x^6 - 6x^5 + 15x^4 - 20x^3 + 15x^2 - 6x +1 leads to severe cancellation. close k=0; for delta = [.1 .01 .008 .007 .005 .003 ] x = linspace(1-delta,1+delta,100)’; y = x.^6 - 6*x.^5 + 15*x.^4 - 20*x.^3 + 15*x.^2 - 6*x + ones(100,1); k=k+1; subplot(2,3,k) plot(x,y,x,zeros(1,100)) axis([1-delta 1+delta -max(abs(y)) max(abs(y))]) end Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 18 Resultatet visas i bilden nedan, där x–axlarna ritas mitt på graferna, för att man skall se avvikelser både uppåt och nedåt. Som vi ser, uppstår ett nästan kaotiskt beteende, då ”förstoringen” ökas. Det ser ut som om polynomet skulle ha tusentals nollställen! Om vi istället hade beräknat polynomet med formeln p(x) = (x − 1)6, skulle vi ha få det väntade utseendet på graferna. Detta betyder, att formler som matematiskt är ekvivalenta, kan bete sig helt olika när de används i ett datorprogram. Introduktion till vetenskapliga beräkningar I, Tom Sundius 2009 JJ J I II × 19