F3: Funktioner (kap. 5) Lab-läget? Konton OK? Matlab nerladdad? Lab 2: Funktioner Funktionsfil, funktionsanrop in- och utparametrar, anropsin- och anropsutparametrar lokala, globala (och persistenta) variabler lokala funktioner return variabelt antal parameterar, skönsvärde (Eng. default) slumptal: Brownsk rörelse profilering pre-allokering 2D som komplexa tal intervallhalvering Lab2 igen, minsta-kvadrat-anpassning avlusning, felsökning (debugging), programprofil slide 1 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Lab 2 Laboration 2 Efter den här laborationen ska du kunna skriva lite större program som är uppdelade i egendefinierade funktioner. Polynomanpassaren 1) Ange gradtal 2) Ange punkter 3) Beräkna koefficienter 0) Avsluta Du ska själv skriva en funktion för varje menyval utom»avsluta». Så här ska de anropas från huvudprogrammet: degree = askdegree(); Frågar efter, läser in och returnerar gradtal. points = askpoints(); Frågar efter, läser in och returnerar punkterna. coeffs = findcoeffs(degree, points); Löser det linjära (överbestämda) ekvationssystemet och returnerar polynomets koefficienter. Du får inte använda polyfit; se nedan om minsta kvadrat-polynom slide 2 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Förslag på arbetsordning: 1. Börja med att konstruera funktioner som inte gör annat än skriver ut sitt namn. 2. Konstruera menyn och anropa för respektive val rätt funktion. Inget ska hända när användaren väljer något, utom att programmet avslutas när man väljer Avsluta. 3. Gör färdigt funktionerna i tur och ordning. Testa dem var och en för sig! slide 3 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Funktioner forts. En funktion är en följd kommandon i en m-fil som inleds med ett funktionshuvud: function [utparameter1, ] = funktionsnamn(inparameter1, ) eller function funktionsnamn(inparameter1, ) Direkt efter funktionshuvudet skriver man dokumentationskommentarer enligt reglerna för lookfor och help. Därefter står kommandon som utförs när funktionen anropas. Funktionen anropas med: funktionsnamn(anropsinparameter1, ) eller [anropsutparameter1, ] = funktionsnamn(anropsinparameter1, ) När kommandona i funktionen har utförts till slut fortsätter exekveringen efter anropet. En funktion bör lagras i en fil med namnet funktionsnamn.m. slide 4 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
slide 5 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Parametrar Parametrarna och övriga variabler i en funktion är lokala dvs. har inget med variabler med samma namn i kommandofönstret eller andra kommando- eller funktionsfiler att göra. Undantag gäller globala och persistenta variabler. Funktioner kan skrivas så att de, olika gånger, kan anropas med olika antal in- och utparametrar. En m-fil kan innehålla mer än en funktion. Funktionerna efter den första kallas lokala funktioner och de syns bara för funktionerna i den m-filen. Vi gör om kommandofilen för kuggväxel till en funktion: function [bestm bestn finalgear] = findgear(gear,nmin,nmax) % Hittar det kugghjulspar som bäst % approximerar en given utväxling. % [m n finalgear] = findgear(gear,nmin,nmax) % hittar den bästa approximationen m/n till % gear för m och n mellan nmin och nmax för % positiva nmin, nmax och gear. slide 6 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
if gear>0 & nmax>0 & nmin>0 bestdiff = realmax; for m = nmin:nmax nprel = floor(m/gear); for n = max(nprel,nmin):min(nprel+1,nmax) diff = abs(m/n-gear); if diff<bestdiff bestdiff = diff; bestm = m; bestn = n; end % if end % for n end % for m finalgear = bestm/bestn; else bestm = NaN; bestn = NaN; finalgear = NaN; error('felaktiga indata.'); end slide 7 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Kuggväxel forts. Testkörning ger: >>findgear(3.14159,5,50) ans = 22 >>[m n g] = findgear(3.14159,5,50) m = 22 n = 7 g = 3.1429 >>findgear(3.14159,5,-50)??? Error using ==> findgear Felaktiga indata. slide 8 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Parametrar forts. Anropsinparametrarna är uttryck. Vid anropet kopieras uttryckens värde till motsvarande inparameter. När funktionen har exekverat färdigt kopieras utparametrarnas värden till motsvarande anropsutparametrar. Anropsinparametrarna kan då inte förstöras av funktionsanropet pass by value. Anropsutparametrarna får vara färre än utparametrarna. Funktionen har exekverat färdigt när sista kommandot eller sista kommandot före nästa funktion har utförts eller när kommandot return utförts. Vi ändrar funktionen så att skönsvärdena för nmax och nmin blir 100 resp. 5. För sådant använder man funktionerna nargin, nargout, nargcheck, error, warning och inputname. function [m n finalgear]=findgear(gear,nmin,nmax) % % positiva nmin, nmax och gear. Skönsvärde slide 9 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
% för nmax och nmin är 100 resp. 5. msg = nargchk(1,3,nargin); error(msg); if nargin<3 nmax = 100; end if nargin<2 nmin = 5; end... Testkörning ger: >>[m n g] = findgear(pi,25) m = 88 n = 28 g = 3.1429 >>[m n g] = findgear(3.14159) m = 22 n = 7 g = 3.1429 >>[m n g] = findgear??? Error using ==> findgear Not enough input arguments. >>[m n g] = findgear(17,10,50,50)??? Error using ==> findgear Too many input arguments. slide 10 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Kuggväxel forts. Man kan på liknande sätt göra funktionen beroende av antalet anropsutparametrar. m = findgear(3.14159) m = 22 [m n] = findgear(3.14159) m = 22 n = 7 slide 11 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Globala variabler Programmera en räknare som kan stegas med anrop till count( ) och avläsas med getcount( ). Själva räknaren måste nås av båda funktionerna. Vanliga variabler i funktioner är ju lokala. Vi gör en variabel, COUNTER, global. Man brukar skriva globala variabler med versaler. I filen count.m: I filen getcount.m: function count function c = getcount % Stegar räknaren COUNTER % Avläser räknaren COUNTER global COUNTER global COUNTER if isempty(counter) c = COUNTER; COUNTER = 0; end COUNTER = COUNTER+1; slide 12 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Global variabel forts. Testkörning: >>getcount ans = [] >>count; count; getcount ans = 2 >>COUNTER??? Undefined function or variable 'COUNTER' En variabel som ska sparas mellan anrop men bara behöver nås inuti en funktion kan istället göras persistent. slide 13 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Slumpvandring Programmera Brownsk rörelse/slumpvandring i planet med lika sannolikhet för alla riktningar, förflyttning sträckan 1 per steg och start i origo. Låt filen brown.m innehålla: function pos = brown(steps,runs) % Simulerar Brownsk rörelse/slumpvandring i 2D. % pos = brown(steps) ritar en vandring med steps % steg. % pos = brown(steps,runs) ritar slutpunkterna av % runs stycken vandringar med vardera steps steg. % pos = sista slutpunkten slide 14 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Slumpvandring forts. msg = nargchk(1,2,nargin); error(msg); if nargin==1 pos = b(steps,1); else pos = []; for run = 1:runs pos = [pos b(steps,0)]; % pos växer se MLINT end plot(pos(1,:),pos(2,:),'ko'); pos = pos(:,end); end slide 15 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Alternativ med pre-allokering... pos = zeros(2,runs); for run = 1:runs pos(:,run) = b(steps,0); end... slide 16 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Slumpvandring forts. Som lokal funktion i samma funktionsfil: function pos = b(steps,show) % Simulerar en slumpvandring med steps steg % och plottar den om show är sant. pos = [0;0]; x = pos; % kolonn (x;y) for k = 1:steps a = rand*2*pi; % Rekt.fördeln. på (0,2π) pos = x(:,end)+[cos(a);sin(a)]; x = [x pos]; end if show plot(x(1,:),x(2,:),'k-'); axis equal end slide 17 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Alternativ utan slinga, med komplexa tal function pos = b(steps,show) % Simulerar en slumpvandring med steps steg % och plottar den om show är sant. a = rand(1,steps)*2*pi; % alla slumptal i rad-vektor dz = exp(1i*a); % z = x+iy steg i x & y-led z = [0,cumsum(dz))]; % kumulativ summa: dz1, dz1+dz2, dz1+dz2+dz3, % diff(cumsum(z)) = (z2,z3,z4,...) = z(2:end) % cumsum(diff(z)) = (z2-z1,z3-z1,z4-z1,...) = z(2:end)-z1 pos = [real(z(end));imag(z(end))]; % (x;y) if show plot(z,'k-'); % matlab förstår komplexa tal axis equal end slide 18 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Testkör: brown(100) brown(100,1000) slide 19 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Slumpvandring forts. Hur ser punktsvärmen ut? o Summan av n (=100) oberoende stokastiska variabler med medelvärde m och varians σ närmar sig N(mn, n σ) då n blir stor. Medelvärdet av sin och cos är noll, och variansen hos sin(r[0,2π]) är = π 1 σ 2 π =. Så x n och y n blir N(0, n / 2), n / 2=7, faktiskt 2 oberoende o Därmed blir sannolikhetstätheten för (x n,y n ) P( x < x n < x + dx & y < r 2 y n < y + dy) =... = 1 e πn x 2 + y n 2 dxdy vilket betyder att 1 e n av punkterna bör hamna innanför cirkel med radie r. r = 10 ger ca 70% - verkar OK. slide 20 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Felsökning igen När programmet inte ger önskat resultat: Läs koden, ändra i programmet Prova att köra med andra indata När ett fel hittas, rätta det och testa igen leta efter ett fel i taget! Lägg in spårutskrifter eller brytpunkter för att se i vilken ordning kommandona utförs och vissa variablers mellanresultat (ta bort ;, lägg in disp eller keyboard). Intervallhalvering Det finns ett särskilt fönster för att skapa profil för ett program, dvs. uppgifter om hur många gånger programmets olika delar/rader har exekverats, och om hur lång exekveringstid som går åt för respektive del. Kommandot tic startar tidtagning och toc avläser och returnerar tid sedan senaste tic. tic; do_it; elapsed_time = toc; slide 21 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Intervallhalvering preludium till ekv.lösning Jämför med algoritmen för pumpa-gissning! Uppgift: Finn nollställe till f(x), givet två startgissningar a < b sådana att f(a) f(b) < 0 om f är kontinuerlig vet vi då att det finns minst ett nollställe i (a,b). Algoritm: 1. c := (a+b)/2; 2. om f(c) f(a) > 0 a := c annars b := c 3. om b-a > tolerans, gå till 1, annars klart slide 22 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
matlab Antag att funktionen f är definierad och heter f_test % intervall-halvering: finn nollställe till f_test(x) % Preludier: kontrollera f(a)f(b)<0 och sätt tolerans while 1 a = input('a: '); b = input('b: '); if f_test(a)*f_test(b) < 0 % OK break else disp(' f(a)f(b) > 0, ge nya a, b!'); end end tol = 1e-6; slide 23 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Matlab k = 0; while abs(b-a)>tol k = k+1; c = (a+b)/2; if f_test(c)*f_test(a) > 0 %?? 2 f-eval per steg? a = c; % vi har ju redan f(a)? else b = c; end end disp(['rot: ',num2str(c),' #iter.: ',num2str(k)]); slide 24 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
slide 25 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03 Effektivitet - algoritm Alltid konvergens under givna förutsättningar, men Det krävs ca. log2( b-a /tol) evalueringar av f Det räcker att f är kontinuerlig Snabbare algoritmer använder mera information om f, t.ex Newton: ett-stegs, kräver derivata ) ( ) ( 1 n n n n x f x f x x = + Sekant: två-stegs, ingen derivata behövs ) ( ) ( ) ( 1 1 1 + = n n n n n n n x f x f x x x f x x
Lab 2 igen, minsta-kvadrat-polynom Kolonn-vektorerna x och y givna. Lös Ac = y. A s kolonn j ska ha potensen N+1-j av x-värdena. Konstruera matrisen A kolonn för kolonn: A = zeros(m,n+1); % pre-allokera A(:,N+1) = ones(m,1); for k = N:-1:1 A(:,k)=A(:,k+1).*x; end; och beräkna koefficienterna i minsta-kvadrat-lösningen med \: c = A \ y; slide 26 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Använda Matlab i rapport Det finns möjlighet att skriva Matlab så att körning av programmet skapar ett dokument som innehåller förklarande text, programavsnitt och resultat från körningen. Dokumentet kan göras i olika format såsom HTML, XML, MSWord, Latex. Varje cell (se F2 om celler) blir ett avsnitt med det som står efter %% som rubrik. Textdelar inom $$ $$ tolkas som TeX, text inom sätts som fastbreddstext, <<filnamn>> sätter in en bild, * text sätter in ett element i en oordnad lista, och # text sätter in ett element i en numrerad lista, HTML-kod kan sättas in direkt, *text* ger halvfet och _text_ ger kursiv text. Funktioner kan hanteras om man inte utför dem vid publiceringen. slide 27 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03
Ö3: 5.2, 5.7, 5.14, 5.20 slide 28 of 28 Staffan Romberger / JO, CSC, KTH, 2012-09-03