/* [wxMaxima batch file version 1] [ DO NOT EDIT BY HAND! ]*/ /* [ Created with wxMaxima version 17.10.0 ] */ /* [wxMaxima: title start ] Luento 4 [wxMaxima: title end ] */ /* [wxMaxima: section start ] Ajankohtaista [wxMaxima: section end ] */ /* [wxMaxima: comment start ] Tämä on viimeinen luento. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Kommentointia ja kuvien piirtämistä kannustetaan erityisesti viimeisessä kahdessa harjoitustehtäväsarjassa. Myös Maximan komentoihin voi laittaa kommentteja ympäristöllä /* Kommentti */ Tämä kuitenkin toimii vain jos samassa solussa on myös jokin oikea komento. Parasta on kommentoida erillisillä tekstisoluilla. [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ 1+1 /* Lasketaan 1+1 */ ; 2+2 /* Lasketaan myös 2+2 mutta ei tulosteta sitä $-merkin takia */ $ /* [wxMaxima: input end ] */ /* [wxMaxima: section start ] Lisää ohjelmointia [wxMaxima: section end ] */ /* [wxMaxima: subsect start ] Kertausta [wxMaxima: subsect end ] */ /* [wxMaxima: comment start ] Tällä luennolla opetellaan lisää keinoja funktioiden määrittelemiseen. Muistetaan, että Maximassa funktio on asia joka ottaa vastaan yhden tai useamman syötteen, tekee syötteiden avulla jotain asioita, ja palauttaa käyttäjälle jotain. Tässä tehtävistä pari esimerkkiä: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ deriv_sijoitus(lauseke,muuttuja) := subst(muuttuja = 5, diff(lauseke,muuttuja))$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Tämän voi myös määritellä vaiheittain: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ uusi_deriv_sijoitus(lauseke,muuttuja) := ( derivaatta:diff(lauseke,muuttuja), subst(muuttuja = 5, derivaatta) /* Viimeinen komento on palautettava arvo. */ )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Tämä funktio siis derivoi annetun lausekkeen annetun muuttujan suhteen, ja sijoittaa muuttujan paikalle luvun 5. [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ deriv_sijoitus(x^2,x); /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ uusi_deriv_sijoitus(x^2,x); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Ja vielä: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ nelio_integraali(lauseke,muuttuja) := integrate(lauseke^2,muuttuja,0,1)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Tämä funktio siis integroi annetun lausekkeen neliön annetun muuttujan suhteen välillä [0,1]. [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ nelio_integraali(x^2,x); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Seuraavissa esimerkeissä nähdään vähän monimutkaisempia funktioita ja uusi tapa määritellä niitä. [wxMaxima: comment end ] */ /* [wxMaxima: subsect start ] Block-ympäristö [wxMaxima: subsect end ] */ /* [wxMaxima: comment start ] Lasketaan aluksi kahden ison luvun summa ja tallennetaan se muuttujaan [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ summa:435892+12893981; /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Palautetaan mieleen Maximassa silmukkojen ja ehtolauseiden syntaksi: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ matriisi1:apply(matrix,makelist(makelist(random(7)-3,6),4)); /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ length(matriisi1); /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ length(transpose(matriisi1)); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Määritellään nyt funktio joka laskee annetun matriisin positiivisten alkioiden summan: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ pos_alkio_summa(matriisi) := ( summa:0, /* alustetaan summaksi 0 */ apumuuttuja:0, /* silmukassa halutaan käyttää apumuuttujaa */ rivien_lkm:length(matriisi), /* lasketaan rivien ja sarakkeiden lukumäärä */ sarakkeiden_lkm:length(transpose(matriisi)), for i:1 thru rivien_lkm do /* silmukassa käydään jokainen rivi läpi, ja jokaisella rivillä käydään jokainen rivin alkio läpi */ for j:1 thru sarakkeiden_lkm do (apumuuttuja:matriisi[i][j], /* tallennetaan apumuuttujaan tällä hetkellä käsiteltävä matriisin alkio */ if apumuuttuja > 0 then summa:summa+apumuuttuja), /* lisätään muuttujaan summa positiiviset alkiot */ summa /* viimeinen pilkulla erotettu asia sulkujen sisällä on arvo jonka lauseke palauttaa, eli se on nyt määrittelemämme funktion arvo */ )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ pos_alkio_summa(matriisi1); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Näyttää toimivan! Tämän kappaleen alussa laskettiin kuitenkin muuttujaan summa arvo 13329873. Katsotaan mikä arvo siellä on nyt [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ summa; /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Käytettiin samaa muuttujaa summa määrittelemään funktio pos_alkio_summa, joten evaluoidessa tätä funktiota arvo vaihtui! Yksi tapa välttää tätä on käyttää aina erinimisiä muuttujia. On kuitenkin fiksumpi tapa: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ summa:13329873; /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ pos_alkio_summa_fiksumpi(matriisi) := block( [summa,apumuuttuja,rivien_lkm,sarakkeiden_lkm], summa:0, apumuuttuja:0, rivien_lkm:length(matriisi), sarakkeiden_lkm:length(transpose(matriisi)), for i:1 thru rivien_lkm do for j:1 thru sarakkeiden_lkm do (apumuuttuja:matriisi[i][j], if apumuuttuja > 0 then summa:summa+apumuuttuja), summa )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Käytettiin ns. block-ympäristöä määrittelemään funktio. Ensimmäisenä block-ympäristön sisällä kerrotaan hakasulkeissa [ ... ] mitä kaikkia muuttujia halutaan käyttää tässä funktiossa. Näistä muuttujista luodaan "lokaalit" versiot funktion kutsun ajaksi jotta mahdolliset niille tallennetut arvot eivät katoa. [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ pos_alkio_summa_fiksumpi(matriisi1); /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ summa; /* [wxMaxima: input end ] */ /* [wxMaxima: subsect start ] Arvojen palauttamisesta [wxMaxima: subsect end ] */ /* [wxMaxima: input start ] */ kill(all); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Kuten huomattiin, block-ympäristössä voi esiintyä useampi lauseke peräkkäin. Arvo jonka näin määritelty funktio palauttaa on viimeinen näistä lausekkeista: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ testifunktio(arvo):=block( [x,y,z,w], x:arvo, x:x-1, y:x^2, w:z+6, w+2, y+3 )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ testifunktio(3); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Return-komennolla voidaan kuitenkin palauttaa asioita keskeltäkin: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ testifunktio2(arvo):=block( [x,y,z,w], x:arvo, x:x-1, y:x^2, w:z+6, return(w^2), w+2, y+3 )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ testifunktio2(3); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Tässä esimerkki, joka perustuu kuuluisaan avoimeen matemaattiseen ongelmaan. Määritellään funktio seuraavasti: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ collatz(n) := block( if mod(n,2) = 0 then return(n/2) else return(3*n+1) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ collatz(7); /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ collatz(%); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Ajamalla jälkimmäisin solu päädyttiin lopulta ykköseen. Collatzin konjektuuri väittää, että laskemalla funktiota collatz() riittävän monta kertaa annettuun posiitiiviseen kokonaislukuun päädytään lopulta aina ykköseen. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Käytetään while-looppirakennetta määrittelemään funktio, joka luo annetun luvun "polun" ykköseen iteroinnissa: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ collatz_polku(n) := block( [lista,apumuuttuja], lista:[], apumuuttuja:n, while apumuuttuja > 1 do /* Muistetaan, että while-silmukka toistaa siihen kirjoitettua komentoa kunnes sille annettu ehto ei enää toteudu */ ( lista:append(lista,[apumuuttuja]), apumuuttuja:collatz(apumuuttuja) ), lista:append(lista,[1]), lista /* Palautus viimeisestä komennosta ellei toisin sanottu. */ )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ collatz_polku(7); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Entä jos ei tykätä luvusta 26 ja halutaan lopettaa silmukka aina jos luku 26 esiintyy jonon jäsenenä? Kokeillaan laittaa return silmukan sisälle: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ collatz_polku2(n) := block( [lista,apumuuttuja], lista:[], apumuuttuja:n, while apumuuttuja > 1 do ( lista:append(lista,[apumuuttuja]), if apumuuttuja = 26 then return("Osuttiin lukuun 26! Looppi katkaistu!"), apumuuttuja:collatz(apumuuttuja) ), lista:append(lista,[1]), lista )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ collatz_polku2(7); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Oho! Ei toimi. Ongelmana on, että return() toimii eri tavalla silmukoiden sisällä. Itseasiassa silmukat ovat vain lausekkeita, jotka palauttavat yleensä arvon "done": [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ for i:1 thru 3 do 1+1; /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Return-funktion kutsuminen silmukan sisällä pistää sen palauttamaan returniin laitettavan arvon. Tästä ei kuitenkaan yleensä ole käytännössä mitään hyötyä... [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ for i:1 thru 3 do if i = 2 then return(8); /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Voidaan kuitenkin kiertää ongelma seuraavasti: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ collatz_polku3(n) := block( [lista,apumuuttuja,osuiko], lista:[], apumuuttuja:n, osuiko:false, while apumuuttuja > 1 do ( lista:append(lista,[apumuuttuja]), if apumuuttuja = 26 then ( osuiko:true, return(0) /* Tässä palautetaan while-silmukasta nolla ihan vain sen takia, että silmukka loppuisi */ ), apumuuttuja:collatz(apumuuttuja) ), lista:append(lista,[1]), if osuiko then return("Osuttiin lukuun 26! Looppi katkaistu!"), lista )$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ collatz_polku3(7); /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ collatz_polku3(13); /* [wxMaxima: input end ] */ /* [wxMaxima: subsect start ] Vielä yksi esimerkki [wxMaxima: subsect end ] */ /* [wxMaxima: comment start ] Seuraavassa esimerkissä on tavoitteena näyttää, että Maximassa pystyy luomaan aika monimutkaisiakin matemaattisia olioita. Tässä tutustutaan ns. satunnaiskävelyyn. Satunnaiskävelyn idea on, että lähdetään jostain tason/avaruuden pisteestä (aika luonnollinen lähtöpiste on origo) ja otetaan askelia eteenpäin satunnaisesti. Jokainen askel mitä otetaan on samanpituinen (tässä esimerkissä ykkösen mittainen), ja jokaisen askeleen suunta on valittu täysin satunnaisesti. [wxMaxima: comment end ] */ /* [wxMaxima: comment start ] Tehdään ensin 2D-satunnaiskävely. Luodaan vaikka ensin funktio joka ottaa pisteen ja palauttaa uuden pisteen, joka saadaan annetusta pisteestä kulkemalla ykkösen mittaisen askeleen satunnaiseen suuntaan: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ satunnaisaskel(piste):= block([k], k : random(float(2*%pi)), return( [piste[1]+cos(k),piste[2]+sin(k)] ) )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Määritellään nyt satunnaiskävelyn tuottava funktio "kavely", joka ottaa argumentikseen luvun n ja kulkee satunnaista kävelyä n askelta origosta lähtien. Tämä funktio siis palauttaa listan, jossa on kävelyn aikana kuljetut pisteet. [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ kavely(n):=block([lista], lista:[[0,0]], for k:1 thru n-1 do lista:append(lista,[satunnaisaskel(lista[k])]), lista)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Luodaan sitten uusi kävely, jossa on annettu määrä askelia, ja piirretään se: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ pituus:50$ lenkki:kavely(pituus)$ wxdraw2d( points_joined=true, point_type=dot, points(lenkki), color=black, point_type=filled_circle, points_joined=false, point_size = 0.5, points([lenkki[1],lenkki[length(lenkki)]]), proportional_axes = xy, xrange = [-10,10], yrange = [-10,10] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Seuraavaksi ei halutakaan kulkea kiinnitetty määrä askelia, vaan jatketaan kävelyä kunnes päädytään r-säteisen ympyrän ulkopuolelle. Tätä varten täytyy luoda uusi funktio joka tuottaa satunnaiskävelyn joka pysähtyy kun mennään r-säteisen ympyrän yli. While-silmukka toimii tähänkin kätevästi: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ kavely_kunnes(r):=block([lista,k], lista:[[0,0]], k:1, while lista[k][1]^2 + lista[k][2]^2 < r^2 do (lista:append(lista,[satunnaisaskel(lista[k])]), k:k+1), lista)$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Tehdäänpä kolme tällaista kävelyä säteellä r = 50 ja piirretään ne kuvaan: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ wxdraw2d( /*Saat helppolukuisemman kuvan jos muutat wxdraw2d->draw2d*/ points_joined=true, point_type=dot, points(kavely_kunnes(50)), color=red, points(kavely_kunnes(50)), color=green, points(kavely_kunnes(50)), color=black, nticks=500, polar(50,t,0,2*%pi), proportional_axes = xy, xrange = [-50,50], yrange = [-50,50] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: comment start ] Näyttää aika jännältä. Tehdään tästä vielä 3D-versio: [wxMaxima: comment end ] */ /* [wxMaxima: input start ] */ kavely3d(R):= block([lista,k,z,t], lista:[[0,0,0]], k:1, while lista[k][1]^2 + lista[k][2]^2 + lista[k][3]^2 < R^2 do ( z:random(2.0)-1, t:random(float(2.0*%pi)), lista:append(lista,[[lista[k][1]+sqrt(1-z^2)*cos(t),lista[k][2]+sqrt(1-z^2)*sin(t),lista[k][3]+z]]), k:k+1 ), lista)$ /* [wxMaxima: input end ] */ /* [wxMaxima: input start ] */ skaala:30$ draw3d( xyplane=-skaala, points_joined=true, point_type=dot, color=green, points(kavely3d(skaala)), color=blue, points(kavely3d(skaala)), color=red, points(kavely3d(skaala)), color=black, points([[skaala,skaala,skaala],[skaala,-skaala,skaala],[-skaala,-skaala,skaala],[-skaala,-skaala,-skaala]]), points([[skaala,skaala,skaala],[-skaala,skaala,skaala],[-skaala,skaala,-skaala],[-skaala,skaala,skaala]]), points([[skaala,skaala,skaala],[skaala,skaala,-skaala],[skaala,-skaala,-skaala],[skaala,-skaala,skaala]]), points([[-skaala,-skaala,skaala],[-skaala,skaala,skaala]]), xrange = [-skaala,skaala], yrange = [-skaala,skaala], zrange = [-skaala,skaala] )$ /* [wxMaxima: input end ] */ /* [wxMaxima: section start ] Tehtäviä [wxMaxima: section end ] */ /* [wxMaxima: comment start ] Tällä kertaa ei ole erillisiä luentotehtäviä. Kurssin harjoitustehtäviin saa apua jos tarvitsee. [wxMaxima: comment end ] */ /* Maxima can't load/batch files which end with a comment! */ "Created with wxMaxima"$