torstai 22. helmikuuta 2024

Koulumatematiikka ja alkeellinen ohjelmointi

Lukion opetussuunnitelman mukaan opiskelijan tulisi paljon muun ohella kehittyä hyödyntämään tietokoneohjelmistoja. Tarkemmin ei täsmennetä, mitä tämä oikeastaan tarkoittaa. Todetaan vain tavoitteeksi, että opiskelija osaa käyttä ohjelmistoja kunkin kurssin matemaattisissa tehtävissä. Huippuna on oppia ohjelmoimaan yksinkertaisia algoritmeja. Käytännössä tämä lienee johtanut melko triviaalien asioiden katsomiseen laskimista tai ohjelmistoista ja tutustumiseen muutamiin ohjelmistoihin, joita tuskin myöhemmissä opinnoissa tai elämässä yleensäkään tullaan käyttämään.

Kuitenkin matematiikka voisi tarjota ympäristön, jossa olisi luontevaa oppia ymmärtämään ohjelmoinnin idea. Tällä puolestaan on merkitystä tietotekniikkaa vahvasti hyödyntävässä yhteiskunnassa myös ihmiselle, joka ei koskaan tulisi ohjelmoimaan yhtään mitään. Jonkinlaisena ohjelmoinnin synonyymina usein käytetään koodausta, mutta tämä johtaa minusta harhaan. Kyse ei ole siitä, että pitäisi oppia kirjoittamaan tietyn syntaksin mukaista koodia, vaan periaatteen ymmärtämisestä. Toki mikä tahansa ohjelmointi edellyttää oikeaa syntaksia, mutta tätä ei ole syytä painottaa välttämättömyyttä enempää. 

Mitä tällainen ohjelmointi sitten voisi olla? Viime syksyn pitkän matematiikan ylioppilaskokeen neljäs tehtävä muodostaa hyvän lähtökohdan pohdiskeluille:

Vektorit $\vec{u} = 3\vec{i}+\vec{j}-2\vec{k}$ ja $\vec{v} = \vec{i}+2\vec{j}-2\vec{k}$ virittävät origon kautta kulkevan tason $T$, eli ne ovat tason suuntavektoreita. Määritä pisteen $(6,7,1)$ etäisyys tasosta $T$.

Tämä on kokeen A-osan tehtävä ja sellaisena tarkoitettu ratkaistavaksi varsin perinteiseen tapaan. Se on kuitenkin tehtävä, jonka ratkaiseminen symbolista laskentaa (CAS) hyödyntäen olisi matematiikan oppimisen kannalta perusteltua. Tällöin numeeriset laskut jäävät toissijaisiksi (toisin sanoen ohjelman tehtäviksi), mutta laskija joutuu miettimään algoritminsa rakenteen. Oleellista on, että tehtävän oliot (vektorit, pisteet jne.) esitetään symboleilla, joilla niihin algoritmissa viitataan. Ratkaisu GeoGebralla voisi näyttää seuraavalta (kuvan saa suurennetuksi klikkaamalla):


Tällaisena ratkaisu on oikeastaan ohjelmakoodi. Vaihtamalla tason virittäjävektorit ja tarkasteltava piste saadaan samantien tehtävä ratkaistuksi toisenlaisilla lähtötiedoilla. Näiden komponentit voivat jopa olla symboleja, jolloin tulos on jo aika pahannäköinen algebrallinen lauseke. Ohjelman syöttötietoina ovat siten vektorit $\vec{u}$ ja $\vec{v}$ sekä piste $P$, tuloksena saadaan pisteen etäisyys tasosta.


Luontevaa olisi tällöin kirjoittaa ohjelma erilliseksi tiedostoksi tai muodostaa siitä muusta laskennasta riippumaton itsenäinen funktio. Funktion määrittely näyttäisi periaatteessa seuraavalta:

etaisyys(u,v,p) = function{
q := r*u+s*v;
yhtalo := {dot(p-q,u)=0, dot(p-q,v)=0};
ratkaisu := solve(yhtalo,{r,s});
q1 := substitute(q,ratkaisu);
sqrt(dot(p-q1,p-q1))
}

(Olen siirtynyt englanninkielisiin termeihin, kuten ohjelmakoodissa on luontevaa.)

Käsittääkseni GeoGebra ei tue tämänkaltaista funktioiden määrittelyä eikä edellä oleva koodi ole minkään todellisen ohjelmointikielen mukaista. Riippuen ohjelmointikielen tavasta esittää vektorit funktion kutsu voisi olla edellä mainitun esimerkin tapauksessa

etaisyys((3,1,-2),(1,2,-2),(6,7,1))
tai vain
etaisyys(vec1,vec2,pst)
mikäli lähtötiedot on talletettu näihin symboleihin. Tuloksena saadaan kysytty etäisyys.

Valmiiksi ohjelmoitu funktio avaa tien monimutkaisempien tehtävien yksinkertaiseen ratkaisemiseen. Jos esimerkiksi pitäisi etsiä pisteen $(1,2,3)$ kautta kulkevalta vektorin $3\vec{i}-2\vec{j}+6\vec{k}$ suuntaiselta suoralta $s$ pisteet, jotka ovat etäisyydellä $2$ vektoreiden $\vec{u}$ ja $\vec{v}$ määräämästä tasosta, nämä saadaan muodostamalla ensin suoralla olevat pisteet parametrin $t$ funktiona ja ratkaisemalla sitten kyseeseen tulevat parametriarvot etäisyysfunktion avulla muodostetusta yhtälöstä:

suora := (1,2,3)+t*(3,-2,6)
solve(etaisyys(vec1,vec2,suora)=2, t)

Tämä antaa ratkaisuksi kaksi arvoa parametrille $t$ ja näiden avulla voidaan laskea kyseiset suoran pisteet.

Tällainen funktion määrittely voisi olla ensimmäinen askel ohjelmoinnin opetteluun. Kyseessä olisi luonnollinen osa matematiikan opiskelua. Tarpeen mukaan ohjelmointirakenteita voitaisiin ottaa käyttöön lisää painottamatta asiaa varsinaiseksi ohjelmointikielen syntaksin opetteluksi. Ohjelmoinnin kannalta tavoitteena olisi periaatteen ymmärtäminen, ei koodariksi opiskelu.

Matematiikan kannalta painottuisi kokonaisnäkemys tehtävän ratkaisemisen strategiasta laskun yksityiskohtiin keskittymisen sijasta. Tällaiseen työskentelyyn olisi yleensäkin hyvä oppia, ei yksinomaan matematiikassa. Se ehkä vastaisi myös paremmin opetussuunnitelman tavoitetta "kehittää laskemisen, luovan ajattelun sekä ilmiöiden mallintamisen, ennustamisen ja ongelmien ratkaisemisen taitoja".

Oleellinen edellytys on, että käytössä on laskentaohjelma, joka tukee edellä kuvattua menettelyä. En tarkoin tiedä, mikä tilanne on tavallisimmissa CAS-ohjelmissa. Jos GeoGebra ei tue, niin voisiko sitä kehittää?

Isot symbolilaskennan ohjelmistot kyllä tukevat menettelyä, mutta niiden koulukäyttö ei monestakaan syystä ole järkevää. Lopuksi esimerkki edellä olevista laskuista Mathematicalla suoritettuina.



3 kommenttia:

Jouni Seppänen kirjoitti...
Kirjoittaja on poistanut tämän kommentin.
Jouni Seppänen kirjoitti...

Python on kohtalaisen suosittu ohjelmointikieli, myös opetuksessa, ja sen Sympy-kirjasto soveltuu tällaiseen laskentaan kohtalaisen hyvin vaikka ei olekaan yhtä edistynyt kuin isot CAS-ohjelmistot. Kokeilin tämän kirjoituksen laskuja Pythonissa:

https://colab.research.google.com/drive/12bRwILo0jXU9eRzH7WuKyYZvTcxt_UGB?usp=sharing

SKK kirjoitti...

Katselin laskut läpi. Minusta sen tyyppistä ohjelmointia, että sen voisi aivan hyvin liittää osaksi matematiikan kouluopintoja. Sillä varauksella, että riittävä aika on mahdollista löytää. Vanhoina hyvinä aikoina matematiikassa opeteltiin laskemaan logaritmitauluja käyttäen. Nykyään näiden vastine on lähinnä ohjelmointi.

Pitänee itsekin perehtyä Pythoniin lähemmin.