SL_esim_lin_alg.wxm / 9 Kertausta ja täydennystä. "assume" (%i) integrate(/(a+x^), x); Is a positive or negative? pos; x atan a (%o) a (%i) assume(a>); (%o) [ a > ] (%i) integrate(/(a+x^), x); x atan a (%o) a (%i) facts(); (%o) [ a > ] (%i) properties(a); (%o) [ database info, a > ] (%i) assume(b>); (%o) [ b > ] (%i7) is(a+b>); (%o7) true (%i) is(a*b>); (%o) true (%i9) is(a/b>); (%o9) true (%i) is(ab>); (%o) unknown (%i) forget(a>, b>); (%o) [ a >, b > ] (%i) facts(); (%o) [ ] (%i) properties(a); (%o) [ database info ] (%i) integrate(/(a+x^), x); Is a positive or negative? neg; (%o) log x a x + a a (%i) facts(); (%o) [ ]
SL_esim_lin_alg.wxm / 9. "declare" (%i) [sin(n*%pi), cos(n*%pi)]; (%o) [ sin π n, cos π n ] (%i7) declare(n, integer); (%o7) done (%i) facts(); (%o) [ kind n, integer ] (%i9) [sin(n*%pi), cos(n*%pi)]; (%o9) [, n ] (%i) declare(n, even); (%o) done (%i) facts(); (%o) [ kind n, integer, kind n, even ] (%i) [sin(n*%pi), cos(n*%pi)]; (%o) [, ] (%i) declare(n, odd); declare: inconsistent declaration declare(n,odd) an error. To debug this try: debugmode(true); (%i) facts(); (%o) [ kind n, integer, kind n, even ] (%i) remove(n, even); (%o) done (%i) declare(n, odd); (%o) done (%i7) [sin(n*%pi), cos(n*%pi)]; (%o7) [, ] (%i) remove(n, integer, n, odd); (%o) done (%i9) facts(); (%o9) [ ]. Newtonin menetelmä/yksiulotteinen Oma newtonl(expr, x, x, n) määrää annetun alkuarvon x lisäksi n uutta likiarvoa yhtälölle expr=. Seuraavassa etsitään sinin nollakohta Newtonin menetelmällä: (%i) newtonl(expr,x,x,n):=block([dy,ny,l,xt,x,j], dy:diff(expr,x), ny:xexpr/dy, x:x, l:[x], xt:x, for j: thru n do (x:subst(xt,x,ny), l:append(l,[x]), xt:x), l)$ (%i) x:/$
SL_esim_lin_alg.wxm / 9 (%i) y:sin(x); (%o) sin (%i) dy:ev(cos(x), x=x); (%o) cos Yhtälö y=y+dy*(xx) on pisteen [x,y] kautta kulkevan sinikäyrän tangenttisuoran yhtälö: (%i) tangentti:y+dy*(xx); (%o) cos x + sin (%i) x:newtonl(sin(x), x, float(x), ); (%o) [.7,.7,.9997779,.97 ] Newtonin menetelmä määrää pistettä x seuraavan likiarvon x seuraavasti: kaavana x = x y(x)/y'(x); ja geometrisesti: piirretään käyrälle y=y(x) pisteeseen [x,y(x)] tangentti; uusi likiarvo x on tangenttisuoran ja xakselin leikkauskohdan xkoordinaatti. Jos pisteessä x derivaatta y'(x) on likimain nolla, ajautuu uusi likiarvo x kauas pisteestä x. (%i) wxplotd([sin(x), tangentti], [x,,]); (%t) (%o) Ensimmäisestä lasketusta likiarvosta seuraavaan siirtyminen antaa jo varsin hyvän likiarvon (tässä esimerkkitapauksessa): (%i7) y:sin(x[]); (%o7).799999 (%i) dy:ev(cos(x), x=x[]); (%o).77 (%i9) tangentti:y+dy*(xx[]); (%o9).77 x.7.799999
SL_esim_lin_alg.wxm / 9 (%i) wxplotd([sin(x), tangentti, tangentti], [x,.,]); (%t) (%o) drawkirjaston avulla mutkikkaan kuvan rakentaminen on helpompaa: (%i) load(draw)$ (%i) wxdrawd(xaxis=true, color=blue, explicit(sin(x), x,,), color=red, explicit(tangentti, x,,), color=green, explicit(tangentti, x,.,) )$ (%t). Newtonin menetelmä/moniulotteinen load(draw)$ (%i) load(mnewton)$ (%i) equ:[x^+y^ =, (x)^ + (y)^ = ]; (%o) [ y + x =, y + x = ] (%i) algsys(equ, [x,y]); (%o) [ ] Jostain syystä algsys ei anna k.o. yhtälöparille ratkaisua, vaikka kuvan mukaan reaalisiakin ratkaisuja on kaksi:
SL_esim_lin_alg.wxm / 9 (%i) wxdrawd(user_preamble="set size ratio ", color=blue, implicit( equ[], x,,, y,,), color=red, implicit( equ[], x,,, y,,) )$ (%t) Sopivasti valituille (kuvan avulla määrätyille) alkuarvoille [x,y] usean muuttujan Newtonin menetelmä löytää ratkaisut: (%i7) sol:mnewton(equ, [x,y], [,]); (%o7) [ [ x =.97, y =.79999 ] ] (%i) ev(equ, first(sol)); (%o) [. =,. = ] (%i9) sol:mnewton(equ, [x,y], [,]); (%o9) [ [ x =.799, y =.999 ] ] (%i) ev(equ, first(sol)); (%o) [. =,. = ] Lineaarialgebraa. Joukot ja listat (%i) [7,,,,,,]; (%o) [ 7,,,,,, ] (%i) length(%); (%o) 7 (%i) [7,,,"A",,[,],]; (%o) [ 7,,, A,, [, ], ] Joukko on eri asia kuin lista: (%i) {7,,,,,,}; (%o) {,,, 7, } (%i) length(%); (%o) (%i) {7,,,"A",,[,],,{,}}; (%o) {,, 7,, {, }, [, ], A }
SL_esim_lin_alg.wxm / 9 (%i7) is([,]={,}); (%o7) false (%i) lst_r:makelist( random(), j,,); (%o) [,,,,, 7,,,,, 9,,,, 7,,,,,,, 9,,,,,, 9,,,,,,,,, 9,,,,,,,,,,,, 9,,,,,,,,, 7,,,,,,,,,,,,,,,, 7,,, 7,,,,,, 7,,,,,,,,,,,,,,,,, ] Mistä paikoista y.o. listaa löytyy luku : (%i9) sublist_indices(lst_r, lambda([x], x=)); (%o9) [ 9,, 9, 9 ] Tässä lambda([x], x=) tarkoittaa samaa kuin funktio fp(x):= is(x=), joka testaa onko muuttuja x sama kuin luku (fp on "predikaatti"). Tällaisen predikaattifunktion arvo on true tai false. lambdaesityksessä funktiolle ei anneta nimeä. (%i) fp(x):= is(x=); (%o) fp x := is x = (%i) sublist_indices(lst_r, fp); (%o) [ 9,, 9, 9 ] Listan alkion voi poimia näin: (%i) lst_r[9]; (%o)...tai näin: (%i) part(lst_r, 9); (%o) Muutetaan lista joukoksi (käänteinen operaatio 'joukko > lista' onnistuu komenolla listify): (%i) set_r:setify(lst_r); (%o) {,,,,,, 7,, 9,,,,,,,,, 9,,,,,, } (%i) length(%); (%o) Muodostetaan kaikkien lukujen,..., joukko ja poistetaan siitä joukon set_r luvut: (%i) setdifference( setify(makelist( k, k,,)), set_r ); (%o) {, 7 } Joukosta (tai yleisemmästä objektista) osan voi poimia komennolla part, mutta ei hakasulkuja käyttäen kuten listojen kohdalla: (%i7) part(set_r, 9); (%o7) (%i) set_r[9]; (%o) {,,,,,, 7,, 9,,,,,,,,, 9,,,,,, } 9
SL_esim_lin_alg.wxm 7 / 9 Piirretään y.o. satunnaispisteistön "kuvaaja". Piirtämistä varten xakselille sijoitetaan arvot j=,..., (eli indeksi) ja yakselille listan lst_r arvot. Tätä varten luodaan taulukko lst_xy, jossa on parit [j, lst_r[j]], j=,...,: (%i9) lst_xy:makelist([j, lst_r[j]], j,,); (%o9) [ [, ], [, ], [, ], [, ], [, ], [, 7 ], [ 7, ], [, ], [ 9, ], [, ], [, 9 ], [, ], [, ], [, ], [, 7 ], [, ], [ 7, ], [, ], [ 9, ], [, ], [, ], [, 9 ], [, ], [, ], [, ], [, ], [ 7, ], [, 9 ], [ 9, ], [, ], [, ], [, ], [, ], [, ], [, ], [, ], [ 7, 9 ], [, ], [ 9, ], [, ], [, ], [, ], [, ], [, ], [, ], [, ], [ 7, ], [, ], [ 9, 9 ], [, ], [, ], [, ], [, ], [, ], [, ], [, ], [ 7, ], [, 7 ], [ 9, ], [, ], [, ], [, ], [, ], [, ], [, ], [, ], [ 7, ], [, ], [ 9, ], [ 7, ], [ 7, ], [ 7, ], [ 7, ], [ 7, 7 ], [ 7, ], [ 7, ], [ 77, 7 ], [ 7, ], [ 79, ], [, ], [, ], [, ], [, 7 ], [, ], [, ], [, ], [ 7, ], [, ], [ 9, ], [ 9, ], [ 9, ], [ 9, ], [ 9, ], [ 9, ], [ 9, ], [ 9, ], [ 97, ], [ 9, ], [ 99, ], [, ] ] (%i7) wxplotd([discrete, lst_xy ])$ (%t7) Esitetään taulukon lukuparit punaisina pisteinä: (%i7) wxplotd([discrete, lst_xy], [style, [points,,,] ] )$ (%t7) Vastaava drawgrafiikkakirjaston avulla: load(draw)$
SL_esim_lin_alg.wxm / 9 (%i7) wxdrawd(point_type=filled_circle, color=red, points(lst_xy) )$ (%t7). Vektorit ja matriisit Vektorit esitetään listoina (t.s. hakasulkujen avulla). Muuttujaan, jolle ei ole annettu arvoa, voidaan liittää hakasulkujen avulla indeksi; tässä tilanteessa hakasulut eivät toimi komennon part synonyyminä. (%i7) v:[x[],x[],x[]]; (%o7) [ x, x, x ] (%i7) w:[y[],y[],y[]]; (%o7) [ y, y, y ] Vektoreiden v ja w sisätulo ilmaistaan tavallisella pisteellä: (%i7) v.w; (%o7) x y + x y + x y (%i7) m:matrix([a[,], a[,], a[,]], [a[,], a[,], a[,]], [a[,], a[,], a[,]]); a, a, a, (%o7) a, a, a, a, a, a, Matriisin ja vektorin kertolasku ilmaistaan tavallisella pisteellä: (%i77) m.v; a, x + a, x + x a, (%o77) a, x + x a, + x a, x a, + x a, + x a, (%i7) w.m; (%o7) y a, + y a, + y a, y a, + y a, + y a, y a, + y a, + y a, Huomaa: Maximassa ei ole eri struktuureja rivi ja sarakevektoreille.
SL_esim_lin_alg.wxm 9 / 9. Transpoosi, determinantti ja käänteismatriisi (%i79) transpose(m); a, a, a, (%o79) a, a, a, a, a, a, (%i) determinant(m); (%o) a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, (%i) ident(); (%o) Matriisin muodostaminen, kun paikkaan [j,k] tulevalle alkiolle on kaava: (%i) h[j,k]:=/(j+k); (%o) h j, k := j + k (%i) hm:genmatrix(h,,); (%o) 7 Vaihtoehtoisesti voidaan käyttää komentoa makelist, mutta syntyvä rivivektoreiden lista pitää muuttaa matriisiksi komennon apply avulla: (%i) makelist( makelist(/(j+k), k,,), j,,); (%o) [ [,,, ], [,,, ], [,,, ], [,,, 7 ] ] (%i) apply(matrix, %); (%o) 7 (%i) determinant(hm); (%o)
SL_esim_lin_alg.wxm / 9 Käänteismatriisi voidaan määrätä kahdella tavalla (huomaa kaksikertainen potenssiin korottamista osoittava merkki ^^): (%i7) hm^^(); (%o7) 7 7 (%i) invert(hm); (%o) 7 7 (%i9) %.hm; (%o9). Gramin ja Schmidtin ortogonalisointimenetelmä (%i9) load(eigen)$ (%i9) hm_gs:gramschmidt(hm); (%o9) [ [,,, ], [ 7, 7 7,, 9 ], [ 9,, 9, 9 ], [, 9 7 7,, ] ] 7 7 7 7 7 7 (%i9) hm_gs[].hm_gs[]; 7 (%o9) 7 + 9 (%i9) rat(%); (%o9)/r/ (%i9) hm_gs[].hm_gs[]; (%o9) (%i9) kill(h); (%o9) done. Kiertomatriisin käänteismatriisi Matriisia kutsutaan ortogonaaliseksi, jos se on kääntyvä ja sen käänteismatriisi on alkuperäisen matriisin transpoosi. Tason ja kolmiulotteisen avaruuden ortogonaaliset matriisit ovat kiertoja (tasossa origon suhteen, avaruudessa jonkin akselin suhteen).
SL_esim_lin_alg.wxm / 9 (%i9) m:matrix( [cos(alpha)*cos(beta), sin(alpha)*cos(beta), sin(beta)], [sin(alpha), cos(alpha), ], [cos(alpha)*sin(beta), sin(alpha)*sin(beta), cos(beta)]); (%o9) (%i97) invert(m); (%o97) + + + + + + + + + + + (%i9) trigsimp(%); (%o9) (%i99) transpose(m); (%o99) Kiertomatriisit koordinaattitasoissa (xakselin suhteen kulman alpha verran negatiiviseen kiertosuuntaan, yakselin suhteen kulman beta verran negatiiviseen kiertosuuntaan, zakselin suhteen kulman delta verran negatiiviseen kiertosuuntaan): (%i) mx:matrix([,,], [,cos(delta),sin(delta)], [,sin(delta),cos(delta)]); (%o) cos δ sin δ sin δ cos δ (%i) my:matrix([cos(beta),,sin(beta)], [,,], [sin(beta),,cos(beta)]); (%o) (%i) mz:matrix([cos(alpha),sin(alpha),], [sin(alpha),cos(alpha),], [,,]); (%o)
SL_esim_lin_alg.wxm / 9 (%i) m = my.mz; (%o) =. Vandermonden determinantti (%i) makelist(makelist(a[j]^k, k,,), j,,); (%o) [ [, a, a, a ], [, a, a, a ], [, a, a, a ], [, a,, a ] ] (%i) vdm:apply(matrix, %); a a a a a a (%o) a a a (%i) determinant(vdm); (%o) a a a a + a a + a a a a a + a a a + a + a a a a a + a a a a a a a a a a a a + a + a a a a a + a a a a (%i7) vdm_det:factor(%); (%o7) a a a a a a a a a (%i) vdm^^(); (%o) a a a a a a a + a a + a a a a + a a a a a a a a a + a a + a a a a + a a a a a a + a a a + a a a + a + a + a + a a a + a + a a a + a + a a a a a a a + a a + a a a a + a a a a a a a + a a + a a a a + a a a a + a a a + a a a + a + a + a a a a a a + a a + a a a a + a a a + a + a a a a a + a a + a a a a + a a a + a + a a + a a a + a a a + a + a a a a a + a a + a a a a + a a a a a a a + a a + a a a a + a a a a + a a a + a a a + a (%i9) vdm_ad:ratsimp(vdm_det*%); (%o9) a a a a + a a a a a + a a a a a a a a a a + a a a a + a a a a a a a a a + a a a a a + a a a a + a a a a a + a a a a a + a a a + a a a a a a a + a a a a a + a a + a a a + a a a a a a + a a a a a + a a a a + a a a + a a a a + a a a a a + a a a a + a a a + a a a a a a + a a a a a +
SL_esim_lin_alg.wxm / 9 (%i) adjoint(vdm); (%o) a a a a a a a a a + a a a a a a a a a + a a a a a a a a a a a a a a a a a + a a a a a a a a a + a a a a a + a a + a a a a a a a a a a a a a a a + a + a a a a a a a a a a a + a a a a + a + a a a a a a a a a + a a a a + a + a a a a a a a a a a a (%i) %vdm_ad; (%o) a a a a a a a a a a a a a + a a a a a a a a a a a a a a a a a a a + a a a a a a a a a a a a a a a a a a a + a a + a a a a a a a a a a a a a a + a + a a a a a a a a a a + a a a a a a a a a a a a a a a a a + a a + a a a a a a a a a (%i) ratsimp(%); (%o).7 Lineaariset yhtälöryhmät: linsolve (%i) kill(h); (%o) done (%i) h[j,k]:=random(); (%o) h j, k := random (%i) hm:genmatrix(h,,); 9 (%o) 7 (%i) echelon(hm); (%o) 9 9 (%i7) triangularize(hm); (%o7)
SL_esim_lin_alg.wxm / 9 Miten matriisista muodostetaan sitä vastaava lineaarinen yhtälöryhmä? Kerroinmatriisin ja tuntemattoman vektorin [x,y,z,u] tulo: (%i) hm.[x,y,z,u]; z + 9 y + x + u (%o) z + x + u z + 7 y + x + u (%i9) kill(e); (%o9) done Poimitaan yllä olevan tulon rivit silmukassa muuttujiin e[k]: (%i) for k: thru do e[k]:part(hm.[x,y,z,u], k,); (%o) done Muodostetaan yhtälöryhmä: (%i) lin_equ:[e[]=, e[]=, e[]=]; (%o) [ z + 9 y + x + u =, z + x + u =, z + 7 y + x + u = ] Yhtälöryhmä voidaan ratkaista komennolla linsolve, joka on tarkoitettu nimenomaan lineaarisille yhtälöryhmille, tai komennolla solve: (%i) linsolve(lin_equ, [x,y,z,u]); %r + 9 %r + 9 %r + (%o) [ x =, y =, z =, u = %r ] (%i) solve(lin_equ, [x,y,z,u]); %r + 9 %r + 9 %r + (%o) [ [ x =, y =, z =, u = %r ] ] Lineaarisista yhtälöryhmästä voidaan poimia varsinainen kerroinmatriisi: (%i) coefmatrix(lin_equ, [x,y,z,u]); 9 (%o) 7...tai laajennettu kerroimatriisi (johon viimeiseksi sarakkeeksi lisätään yhtälöryhmän oikean puolen vektori): (%i) augcoefmatrix(lin_equ, [x,y,z,u]); 9 (%o) 7 Sama saataisiin aikaan lisäämällä yhtälöryhmän kerroinmatriisiin sarake näin:
SL_esim_lin_alg.wxm / 9 (%i) hm_a:addcol(hm, [,,]); 9 (%o) 7 Laajennettua kerroimatriisia vastaava yhtälöryhmä voidaan muodostaa myös seuraavasti: (%i7) vek:append([x,y,z,u], []); (%o7) [ x, y, z, u, ] (%i) hm_a.vek; z + 9 y + x + u (%o) z + x + u z + 7 y + x + u (%i9) substpart("[", %, ); (%o9) [ [ z + 9 y + x + u ], [ z + x + u ], [ z + 7 y + x + u ] ] (%i) flatten(%); (%o) [ z + 9 y + x + u, z + x + u, z + 7 y + x + u ] (%i) linsolve(%, [x,y,z,u]); %r + 9 %r + 9 %r + (%o) [ x =, y =, z =, u = %r ]. Ominaisarvot, A (%i) load(eigen)$ (%i) kill(h)$ (%i) h[j,k]:=/(j+k); (%o) h j, k := j + k (%i) hm:genmatrix(h,,); (%o) eigenvalues palauttaa sekä ominaisarvot että vastaavat kertaluvut; tuloksen muoto on [ominaisarvojen lista, vastaavien kertalukujen lista]: (%i) ev_hm:eigenvalues(hm); (%o) [ [, + ], [, ] ] eigenvectors palauttaa sekä ominaisarvot että vastaavat ominaisvektorit; tuloksen muoto on [ [ominaisarvojen lista, kertalukujen lista], ominaisvektoreiden lista ]: (%i7) evek_hm:eigenvectors(hm); (%o7) [ [ [, + ], [, ] ], [ [ [, + ] ], [ [, ] ] ] ]
SL_esim_lin_alg.wxm / 9 Erotetaan ominaisarvot: (%i) l:part(evek_hm,,,); (%o) (%i9) l:part(evek_hm,,,); (%o9) + Erotetaan ominaisvektorit: (%i) v:part(evek_hm,,,); (%o) [, + ] (%i) v:part(evek_hm,,,); (%o) [, ] Tarkistetaan, että ominaisvektorit ja arvot määräävä ehto A.v = l*v toteutuu. Tätä varten lasketaan erotus A.v l*v kummallekin ominaisarvolle: (%i) hm.v l*v; (%o) + + + + + + 9 (%i) ratsimp(%); (%o) (%i) hm.v l*v; (%o) + + + + + + 9 (%i) ratsimp(%); (%o).9 Ominaisarvot, B (%i) load(eigen)$ (%i7) kill(h)$ (%i) h[j,k]:=/(j+k); (%o) h j, k := j + k
SL_esim_lin_alg.wxm 7 / 9 (%i9) hm:genmatrix(h,,); (%o9) Ominaisarvojen lausekkeet ovat melko monimutkaiset ja niiden perusteella ominaisarvot näyttäisivät kompleksisilta: (%i) ev_hm:eigenvalues(hm); (%o) [ [ %i 99 %i + 97 / / + %i 9 99 %i + 97 / + /, %i 99 %i + 97 / / + %i 9 99 %i + 97 / + /, 99 %i + 97 / / + 9 99 %i + 97 / + / ], [,, ] ] Erotetaan ominaisarvot (eli pudotetaan niiden kertaluvut pois):
SL_esim_lin_alg.wxm / 9 (%i) map(rectform, ev_hm[]); (%o) [ %i ( 9 / 9 / 9 sin 9 / 9 / 9 / 9 cos 9 / / cos sin sin atan 9 / 99 7 9 / / / / sin cos sin atan 9 / 99 7 9 / / atan 9 / 99 7 atan 9 / 99 7 / atan 9 / 99 7 9 / cos atan 9 / 99 7 atan 9 / 99 7 atan 9 / 99 7 / + ] + ) + 9 cos 9 / atan 9 / 99 7 9 / sin / / atan 9 / 99 7 9 / cos atan 9 / 99 7 9 / ) + / 9 9 / 9 sin sin / cos / 9 / atan 9 / 99 7 9 / / sin atan 9 / 99 7 9 / / atan 9 / 99 7 atan 9 / 99 7 9 / / cos / sin atan 9 / 99 7 atan 9 / 99 7 9 / +, %i ( / atan 9 / 99 7 + 9 / cos +, %i / + atan 9 / 99 7 9 / cos / + atan 9 / 99 7 + (%i) float(%); (%o) [.797.977 %i,.977 %i +.7779,.77777 7 %i +.97 ] Ominaisarvot määräävä yhtälö on charpoly(hm, x) = :
SL_esim_lin_alg.wxm 9 / 9 (%i) determinant(hm x*ident()); (%o) x x x x x + (%i) charpoly(hm, x); (%o) x x x x x + (%i) p:expand(%); (%o) x + x 7 x 7 + nroots kertoo yhtälön reaalisten juurten lukumäärän (ratkaisematta yhtälöä): (%i) nroots(p=, minf, inf); (%o)