Simo K. Kivelä / 05.05.2003

Yhtälöiden ratkaiseminen

Remove["Global`*"]

Ensimmäisen ja toisen asteen yhtälöt; yleisemmin: polynomiyhtälöt

Luontevinta on aloittaa tallettamalla yhtälö jollekin (kuvaavalle) nimelle. Yhtälön yhtäläisyysmerkki on kaksi peräkkäistä yhtäläisyysmerkkiä; yksi yhtäläisyysmerkki on sijoitusoperaattori, jolla lauseke talletetaan jollekin  nimelle.

yhtalo =  17 x  - 2 == 9

Ratkaisu saadaan komennolla Solve, jolle on annettava kaksi argumenttia: yhtälö ja tuntematon, so. symboli, jonka suhteen yhtälö halutaan ratkaista:

ratkaisu =  Solve[yhtalo, x]

Yhtä hyvin yhtälö voidan suoraan kirjoittaa Solve-komennon argumentiksi:

Solve[17 x - 2 == 9, x]

Ratkaisu saadaan korvaussäännön muodossa. Muuttujalle x ei aseteta arvoa:

x

Mihin tahansa lausekkeeseen voidaan muuttujalle x sijoittaa saatu arvo korvausoperaattorin /. (eli ReplaceAll) avulla:

x^2 /. First[ratkaisu]

yhtalo /. First[ratkaisu]

Vastaavasti toisen asteen yhtälölle:

yhtalo =  a x^2  +  b x  +  c  == 0

ratkaisu =  Solve[yhtalo, x]

Tämän avulla voidaan laskea esimerkiksi juurten summa ja tulo:

(x /. First[ratkaisu])  +  (x /. Last[ratkaisu]) // 
      Simplify

(x /. ratkaisu[[1]]) * (x /. ratkaisu[[2]]) // 
      Simplify

Korvaussännön ratkaisu eri osiin on tässä viitattu ensin funktioilla First ja Last ja sitten indeksillä.

Vastaavaan tapaan voidaan käsitellä korkeampien asteiden yhtälöitä:

Solve[x^3  -  6  x^2  -  x  +  18  ==  0, 
      x]

Joskus tulos voi olla pitkähkö. Seuraavassa muodostetaan yleinen neljännen asteen yhtälön ratkaisukaava, joka talletetaan korvaussäännön muodossa nimelle rtk. Tämä sisältää itse asiassa neljä korvaussääntöä, koska neljännen asteen yhtälöllä on neljä juurta.

poly =  
      a x^4  +  b x^3  +  c x^2  +  d x  +  
        e

rtk =  Solve[poly == 0, x]

Saadun ratkaisukaavan pätevyyttä voidaan testata muodostamalla ensin polynomi, jonka nollakohdat tiedetään, ja yrittämällä sitten ratkaista nämä edellä saadusta yleisestä kaavasta. Polynomi olkoon

p =  (x - 1) (x - 2) (x - 3) (x - 4) // 
        Expand

Sijoitetaan kertoimet edellä saatuun kaavaan ja yritetään sieventää:

rtk /. {a -> 1, b -> -10, c -> 35, d -> -50, e -> 24} // 
      Simplify

rtk /. {a -> 1, b -> -10, c -> 35, d -> -50, e -> 24} // 
      FullSimplify

Aina ei kuitenkaan onnistu. Muodostetaan uusi neljännen asteen polynomi ja ratkaistaan se toisaalta suoraan Solve-komennolla, toisaalta sijoittamalla polynomin kertoimet ratkaisukaavaan.

p =  
      poly /. {a -> 1, b -> 0, c -> 0, d -> 0, 
          e -> -1}

nollakohdat = Solve[p == 0, x]

Nämä ovat todellakin nollakohdat:

p /. nollakohdat

Mutta:

rtk /. {a -> 1, b -> 0, c -> 0, d -> 0, 
        e -> -1}

Saatu ratkaisukaava ei siis olekaan aivan yleinen!

Polynomiyhtälöt numeerisesti

Polynomiyhtälön ratkaiseminen ei aina ole suoraviivaista:

p = x^7 + x + 1

rtk = Solve[p == 0, x]

Nämä ovat kyllä polynomin nollakohdat, mutta niiden lausekkeet ovat hieman erikoiset. Taustalla on vakava periaatteellinen rajoitus: juurilausekkeiden (neliöjuuri, kuutiojuuri jne.) avulla ilmaistavat yleiset ratkaisukaavat ovat olemassa ainoastaan neljänteen asteeseen saakka. Korkeampien asteiden polynomeille voidaan käyttää eo. lausekkeiden tapaisia ilmauksia, jotka ovat oikeastaan vain tautologioita. Numeeriset arvot saadaan kuitenkin tällöinkin:

rtk // N

Toisaalta numeeriset arvot voidaan laskea myös suoraan funktiolla NSolve, mikä saattaa olla oleellisestikin nopeampaa:

NSolve[p == 0, x]

Transkendenttiyhtälöt

Joissakin tapauksissa funktiota Solve voidaan käyttää myös muiden kuin polynomiyhtälöiden ratkaisuun:

rtk = Solve[Sin[5 x] == Cos[3 x], x]

rtk // N

Kaikkia juuria ei kuitenkaan saada.

Yleensä ns. transkendenttiyhtälöiden ratkaiseminen ei kuitenkaan onnistu:

Solve[Log[x] == Tan[x], x]

Tällaisten yhtälöiden numeeriseen ratkaisemiseen on käytettävissä funktio FindRoot. Se käyttää Newtonin menetelmän tyyppistä (mutta tehokkaampaa) algoritmia yhtälön yhden ratkaisun löytämiseen. Algoritmille on annettava jonkinlainen etsittävän juuren alkuapproksimaatio:

FindRoot[Log[x] == Tan[x], {x, 1}]

FindRoot[Log[x] == Tan[x], {x, 6}]

FindRoot[Log[x] == Tan[x], {x, 8}]

Menetelmä ei aina anna alkuapproksimaatiota lähintä juurta, kuten viimeinen esimerkeistä osoittaa.

Alkuarvojen etsimisessä voidaan käyttää graafisia esityksiä:

Plot[{Log[x], Tan[x]}, {x, 0.01, 10}, 
      PlotRange -> {-4, 4}]

Yhtälöryhmät

Kaikkia edellä esitettyjä menetelmiä voidaan käyttää myös yhtälöryhmien ratkaisemiseen. Funktioissa Solve ja NSolve niin yhtälöt kuin tuntemattomatkin on tällöin annettava aaltosulkuihin suljettuina listoina:

Solve[{a x  +  b y  ==  s,  
        c x  +  d y  == t}, {x, y}]

Solve[{u^2 + v^2 == 1, v == u^2}, {u, v}]

NSolve[{u^2 + v^2 == 1, v == u^2}, {u, v}]

Funktion FindRoot syntaksi on hieman erilainen:

FindRoot[{u^2 + v^2 == 1, v == u^2}, {u, 1}, {v, 
        1}]