Lahendajad

Inseneridena kasutame matemaatilisi valemeid, mis kirjeldavad seosed erinevate parameetrite vahel. Näiteks, termodünaamikas on meil olekuvõrrandid, mis kirjeldavad seost olekuparameetrite vahel. Kui tahame teatud parameetrit arvutada, siis me peame lahendama mudeli valemeid soovitud parameetri jaoks. Mõnikord saame seda analüütiliselt lahendada, ehk me saame valemit ringi tõsta nii, et soovitud parameeter oleks eraldi. Kuid mõnikord on raske või võimatu seda teha.

Sellistel juhtudel peame lahendama numbriliselt. Kui lahendame numbriliselt, siis me sisuliselt proovime erinevaid väärtusi kuni leiame väärtust, mis lahendab valemeid. On palju erinevaid optimeerimise algoritme, mida on pakutud selliste ülesannete lahendamiseks. Sisuliselt kõik kasutavad arvuteid kuna oleks tüütu teha neid arvutusi käsitsi.

Siin selgitame lühidalt, kuidas lahendajad töötavad. Näitame ka, kuidas kasutada olemasolevaid lahendajaid Pythoni Scipy paketis ja arvutustabeli tarkvaras.

Näide ülesanne

Termodünaamikas me mõnikord tahame arvutada aine või segu tihedust. Kuid tavaliselt ei ole võimalik olekuvõrrandeid lahendada analüütiliselt tiheduse jaoks. Kasutame siis seda ülesannet näitena. Oletame, et tahame arvutada etaani tihedust tingimustel 20 °C ja 5 bar. Võiksime seda näiteks teha PC-SAFT olekuvõrrandiga.

from pcsaft import pcsaft_den
import numpy as np

t = 293.15 # K
p = 5*1e5 # Pa

x = np.asarray([1.]) # moolosa
m = np.asarray([1.6069]) # parameetrid etaani jaoks
sigma = np.asarray([3.5206])
eps_k = np.asarray([191.42])
params_pcsaft = {'m':m, 's':sigma, 'e':eps_k}

Kuigi pcsaft ja teised paketid ja programmid suudavad tavaliselt ise lahendada selliseid ülesandeid, teeme siin ise selleks, et näha, kuidas lahendajaid kasutada.

Veafunktsioon

Lahendaja peab teama, kas mõni väärtus lahendab valemeid ja, juhul kui ei ole lahendus, kui lähedal see võiks olla lahendusele. Veafunktsioon näitab seda. Veafunktsioonis me arvutame väärtust näitamaks, kui lähedal või kaugel antud parameetri väärtused on lahendusele. Tihti kasutatakse selleks tingimust, et lahenduse juures valemi mõlemad pooled peavad olema võrdsed. Näiteks lahutatakse valemi paremat poolt valemi vasakust poolest ja see väärtus näitab, kui kaugel me oleme lahendusest. Tihti võetakse absoluutväärtust või erinevuse ruutu, nii et viga oleks alati positiivne.

Lahendaja tavaliselt otsib veafunktsiooni miinimumi või maksimumi. Seega, on võimalik ka kirjeldada veafunktsiooni nii, et lahenduse juures veafunktsioon annab kõige suuremat vastust.

Näide ülesandes võime veafunktsioonina kasutada erinevust arvutatud ja tegelikku rõhu vahel. Kui õiget tihedust antakse sisendina olekuvõrrandile, siis arvutatud rõhk võrdub tegeliku rõhuga. Muudame ka erinevust protsendiks kuna rõhu suurusjärk võib oluliselt varieeruda.

def veafunktsioon(den, p, t, x, params):
    p_calc = pcsaft_p(t, den, x, params)
    cost = ((p_calc - p) / p * 100)**2
    return cost

Tuletise meetodid

Lahendaja peab kuidagi otsustama iga kord, mis väärtust proovida. Lahendaja võib lihtsalt suvaliselt valida väärtusi, ja mõnikord tehaksegi seda, aga tavaliselt saab kiiremini leida lahendust, kui targalt valida iga järgmist väärtust.

Tuletise meetodid kasutavad veafunktsiooni tuletist antud punktil, et valida järgmist väärtust, mida proovida. Nii nagu pall veereb mäest alla, tuletise järgi saab ennustada, mis suunas viga läheb väiksemaks ja liikuda selles suunas. Kui otsitakse hoopis maksimumi, siis on sama põhimõte, aga lihtsalt minnakse teises suunas.

Tuletise meetodid sobivad, kui veafunktsioon on pidev. Ehk ei toimu järsk hüppeid. Samuti need töötavad paremini, kui funktsioon on sile. Kui funktsioon on hoopis laineline või konarlik, siis lahendaja võib jääda kohalikus miinimumis kinni ja mitte leida lahendust. See juhtub kuna mõlemal pool tuletis suunab tagasi kohalikusse auku. Mõnikord on ikkagi võimalik leida lahendust, kui anda lahendajale teist algväärtust. Siis lahendaja alustab teisest kohast ja võibolla ei jää kohalikusse miinimumisse kinni. Kui aga ei ole võimalik sedasi lahendada, siis tuleb kasutada globaalset lahendajat.

Globaalsed lahendajad

Globaalsed lahendajad proovivad vältida kohalikke miinimume ja maksimume ja leida kõige paremat lahendust. On palju erinevaid algoritme. Mõned algoritmid kasutavad ikkagi tuletise meetodeid, aga lisavad osa, mis valib erinevaid algväärtusi tuletise meetodi jaoks.

On ka evolutsioonilised algoritmid. Need sisuliselt loovad terve kogumi (või populatsiooni) võimalikke väärtusi ja arvutavad iga liikme jaoks viga. Siis punktid kogumis muudatakse, et tasapisi hakkavad liikuma selle liikme juurde, mis on siiamaani saavutanud kõige paremat väärtust. See peaks sarnanema mõnes mõttes evolutsiooniga, milles aja jooksul kõige paremad organismid populatsioonis jäävad ellu ja annavad geenid edasi järgmisele põlvkonnale.

On veel palju erinevaid optimeerimise algoritme, aga me siin ei anna ülevaadet kõikidest.

Scipy optimize moodul

On palju tarkvara pakette juba olemas optimeerimiseks, mis pakuvad lahendajad. Vaatame siin ühte: Scipy optimize moodul.

Scipy-s on mitu erinevat lahendajat juba olemas. minimize funktsioon annab võimalust kasutada 14 erinevat tuletise meetodit. Saaksime seda kasutada, et leida etaani tihedust.

from scipy.optimize import minimize

den_guess = 5 # mol m^-3
result = minimize(veafunktsioon, den_guess, args=(p, t, x, params_pcsaft))
den = result.x

minimize funktsioonile peame andma funktsiooni, mida see hakkab lahendama, ehk siin veafunktsiooni, mida me varem defineerisime. args parameetriga, saame anda lisa parameetrid edasi oma veafunktsioonile. Näiteks, meie funktsioon vajab rõhku, temperatuuri, moolosad ja PC-SAFT parameetreid. Lisaks, peame andma lahendajale algväärtust: siin den_guess.

Lahendaja väljastab tulemust OptimizeResult objekti, ja selle objekti x parameeter ongi meie vastus. On ka muud informatsiooni. Näiteks, fun annab veafunktsiooni väärtust vastuse juures. Kui see on ikkagi suur, siis võibolla lahendaja ei suutnud leida head väärtust.

Kui sa ei taha vaikimisi algoritmi kasutada, võid anda funktsioonile method parameetri koos soovitud meetodi sõnega.

optimize moodulis on ka globaalsed lahendajad. Üks võimas globaalne lahendaja on differential_evolution funktsioon.

from scipy.optimize import differential_evolution

bnds = ((1e-2, 150),)
result = differential_evolution(veafunktsioon, bounds=bnds, args=(p, t, x, params_pcsaft))
den = result.x

differential_evolution meetodiga antakse algväärtuse asemel piirid. Siin valisime piirideks 0,01 ja 150 mol/m3. Kui piirid on liiga kitsad, siis lahendus on tihti ühe piiri lähedal. Sellisel juhul võib piiri laiendada ja uuesti jooksutada programmi.

Kui su arvutil on mitu tuuma võid kasutada mitu korraga, et optimeerimine oleks kiirem. Anna differential_evolution funktsioonile lisa parameeter workers. Kui tahad kasutada kõik tuumad pane väärtuseks -1.

Lahendajad arvutustabeli tarkvaras

Arvutustabeli tarkvaras on ka lahendaja. Kuigi programmeerimise keeles on valikuid palju rohkem, mõnikord on mugavam kasutada arvutustabeli lahendaja.

Kui kasutada lahendajat arvutustabelis, on vaja panna algväärtused lahtritesse. Samuti on vaja defineerida ühes lahtris oma veafunktsiooni. Veafunktsiooni arvutamiseks võib kasutada mitu lahtrit ja vahepealsed väärtused kokku liita lõplikuks veaväärtuseks.