Hlavní navigace

Octave - programovací jazyk pro neprogramátory

8. 9. 2003
Doba čtení: 11 minut

Sdílet

Potřebujete počítat s maticemi, numericky integrovat nebo něco počítat iteraktivně? Nepotřebujete k tomu ani "velkou" kalkulačku ani umět typické programovací jazyky, jako je třeba C++. Octave má jednoduché instrukce (chce to, pravda, umět trochu anglicky) a můžete počítat jednoduše - vzoreček po vzorečku přepisovat na příkazovou řádku a dostávat mezivýsledky. Octave umí řešit i lineární a nelineární soustavy algebraických rovnic a obyčejných diferenciálních rovnic.

Octave umí i dávkově zpracovávat již dříve napsané programy, či spíše pro svou jednoduchost prográmky. Pracuje na terminálové obrazovce, místo překladače používá interpreter, nemusíte deklarovat spoustu proměnných, i výpisy na obrazovku jsou programátorsky jednodušší. Syntaxe Octave přitom vychází ze známých programovacích jazyků, jako jsou C++ a Fortran.

Tento článek si neklade nárok na úplnost a vychází z dokumentace na webových stránkách Octave a z helpu vyvolaného přímo z shellu. Jeho cílem je zjednodušit potenciálním uživatelům začátky.

Základní vlastnosti

GNU Octave je vyšší programovací jazyk zaměřený na numerické operace. Je velmi podobný jazyku MATLAB. Je vhodný pro ty, kterým nedělá problémy algoritmizace, ale vadí jim složité implementační záležitosti, které je pronásledují např. při programování v C++. Ocení ho ale i ti, kteří potřebují vykonávat složitější výpočty krok po kroku a nemají po ruce vhodnou kalkulačku.

Autorem jazyka Octave je John W. Eaton a, jak píše na domovské stránce Octave, mnoho dalších přispěvatelů. Vznikl původně jako pomůcka pro studenty, kterým zabíralo příliš mnoho času učit se Fortran, a měl jim pomoci s praktickými výpočty. Octave je navržen tak, aby ti, co potřebují něco spočítat, nemuseli věnovat spoustu času učení se nějakému „klasickému“ programovacímu jazyku. Nevím, zda vznikl Octave jakožto open-source „kopie“ MATLABu (MATLAB je registrovaná obchodní značka společnosti MathWorks, Inc.) nebo naopak MATLAB vznikl z Octave (či podle Octave) dodáním spousty užitečných (oborových) toolboxů. Poslední dokumentace patří k verzi 2.0.10, poslední stabilní verze má číslo 2.0.17. Celou dokumentaci lze nalézt na webových stránkách Octave.

Jazyk Octave je postaven na maticích. Všechny operace jsou maticové, jen někdy jsou tyto matice jednoprvkové. Matice mohou mít jak reálné, tak i imaginární členy. Jazyk umožňuje též numerickou integraci soustav jednoduchých diferenciálních rovnic nebo soustav jednoduchých diferenciálních a algebraických rovnic.

Čas ušetří mimo jiné fakt, že není nutno proměnné předem deklarovat a specifikovat, zda bude typu celočíselného, reálného, či zda to budou písmena. Lze i vytvořit datovou strukturu, která bude v sobě obsahovat proměnné všech těchto typů a některé z nich budou i jedno- nebo dvourozměrné (vektory nebo matice) – viz původní dokumentaci. Další příjemnou vlastností je to, že funkce může vracet jakýkoli počet jakýchkoli argumentů, aniž by se programátor musel zabývat ukazateli. O způsobu psaní funkcí bude pojednáno později.

Velice sympatickou vlastností shellu je ukládání posloupnosti provedených příkazů (= vzorců) v souboru ~/.octave_hist a jejich možné vyvolání i po restartu shellu. Vyvolávání starších příkazů se provádí šipkou nahoru. Dalším zpříjemněním práce je doplňování příkazů na příkazové řádce (pomocí tabelátoru), toto ale bohužel nebere v úvahu historii, ale pouze používané proměnné, příkazy Octave a názvy dostupných souborů (mj. skriptů a funkcí, které jsou v dosahu – tj. v aktuálním adresáři a v adresářích nastavených v proměnných LOADPATH a DEFAULT_LOADPATH).

Chcete-li už dnes s prací skončit, ale úlohu jste ještě neukončili, není nic jednoduššího než si důležité (nebo všechny) proměnné uložit. K tomu slouží příkaz save file prom, kde file je název souboru, který chcete pro uložení použít, a prom je jméno vaší proměnné, kterou chcete uložit (může být i více proměnných, bez parametru uloží všechny vaše proměnné). Až si budete chtít příště proměnné načíst, stačí zadat příkaz load file (kdefile je opět jméno souboru). Oba tyto příkazy mají i přepínače (určují formát souboru) – blíže viz původní dokumentaci. Pro úplnost dodejme ještě dva příkazy pro práci s prostory proměnných (tzv. workspace ), a to who (zobrazí všechny vámi používané proměnné) a clear (všechny proměnné vymaže).

V shellu samozřejmě fungují základní operace pro práci se systémem souborů – operace cd, ls apod., pokud nejsou přepsány proměnnou.

Interpreter Octave (se shellem) se dá stáhnout na domovské stránce Octave a je součástí linuxových distribucí Debian, SuSe a RedHat. Distribuuje se pod GNU GPL licencí a funguje kromě Unixu podobných systémů i na Windows NT/95 a OS/2.

Jednoduchý help

Základní operace, matice

Chcete-li proměnné a přiřadit hodnotu 5, stačí napsat a=5. Pak se vám vypíše řádek oznamující, co se změnilo, a na něm bude opět a=5. Chcete-li z jakéhokoliv důvodu tento výpis potlačit, stačí příkaz ukončit středníkem a=5;. Má-li být a matice (nebo dvourozměrné pole), stačí napsat např. a=[5 7;12 13], kde mezera (nebo čárka) odděluje prvky v jednom řádku a středník odděluje od sebe jednotlivé řádky. Celá matice musí být uzavřena v hranatých závorkách. Samozřejmě je možno zadat i vektor (jednorozměrné pole), a to jak řádkový, tak i sloupcový. Chceme-li zavést pole nul, napíšeme a=zeros(n,m), kde n je počet řádků a m je počet sloupců vytvořené matice. Zadáme-li jen jeden parametr, vytvoří se čtvercová matice. Obdobně lze použít příkaz onespro pole jedniček a příkaz eye pro jednotkovou matici (pouze jeden parametr). Diagonální matici můžeme jednoduše zadat pomocí funkce diag(v), kde v je vektor (jednorozměrné pole) čísel, které se na diagonále objeví.

Pro psaní vzorců se používají znaky +, -, *, /,^, kulaté závorky apod., stejně jako na běžné kalkulačce. Dodejme pro úplnost, že Octave patří mezi „lepší kalkulačky“, kterým nedělá problém přednost násobení před sčítáním. Taktéž lze použít standardní (Cčkovské) operátory &, &&, |, ||, --, ++ (poslední dvě jmenované operace se u matic provedou pro každý prvek zvlášť). Pokud chceme použít maticové násobení, mocnění apod., použijeme opět operátory , ^, pokud však chceme násobit dvě pole (tj. vynásobit vždy dva prvky na stejném místě) nebo mocnit každý prvek matice (nebo vektoru) zvlášť, použijeme operátory ., .^, ./. Transponovaná matice se značí apostrofem, tj. chceme-li matici a transponovat, napíšeme a=a'. Lze pochopitelně násobit matici skalárem a lze i přičítat (a odečítat) skalár k matici – pak se onen skalár přičte ke všem prvkům matice.

K řešení lineárních algebraických rovnic typu ax=b se používá levé dělení (matic) a\b, které funguje i pro přeurčenou soustavu, kde spočte optimální řešení ve smyslu nejmenších čtverců. Inverzní matici matice a získáme příkazem inv(a) nebo jednoduše a^(-1). K dispozici jsou i další operace s maticemi – determinanty, pseudoinverze, vlastní čísla a vektory, různé faktorizace a další. Tyto zde již nebudeme podrobně rozepisovat; zájemce získá jejich popis v původním manuálu nebo helpu.

Do matic či polí se dá pochopitelně přistupovat i jednotlivě – indexy se vkládají do kulatých závorek; např. prvek ve 3. řádku a 2. sloupci matice a adresujeme jakožto a(3,2). Chceme-li z matice vyextrahovat 2. řádek (výsledkem bude řádkový vektor), napíšeme a(2,:); operátor dvojtečky se zde používá jako zástupce za všechny sloupce. (Obdobně bude vypadat, chceme-li z matice vyextrahovat sloupec.) Zmiňme se též o funkci size(a), která nám vrátí velikost matice (první číslo je počet řádků, druhé počet sloupců). Funkce columns(a) nám vrátí počet sloupců, funkce rows(a) počet řádků, funkce length(a) ten větší z nich. Operátor dvojtečky má jedno zajímavé rozšíření: napíšeme-li např.a(1:2:row­s(a),2), dostaneme jednorozměrný vektor obsahující každý druhý (krajní čísla u dvojteček udávají začátek a konec intervalu, prostřední číslo (když je vynecháno, uvažuje se 1) „častost“ výběru z tohoto intervalu) prvek druhého sloupce matice.

Nevýhodou současné verze Octave je to, že nepodporuje více než dvourozměrná pole (MATLAB verze 6 je již podporuje).

Komplexní čísla se zadávají jednoduše: a=1+3i. Zde mohu doporučit funkce abs(a), arg(a), imag(a), real(a) aconj(a).

Samozřejmostí každé lepší kalkulačky jsou goniometrické, hyperbolické funkce a logaritmy.

Textové vstupy a výstupy

Textové výpisy na terminál jsou jednoduché – slouží k nim funkce disp s jedním parametrem, kterým může být buď řetězec uzavřený v uvozovkách, nebo proměnná. Taktéž je možno provádět výpis proměnné pomocí vynechaného středníku za přiřazením. Složitější výpisy (např. více proměnných na jednu řádku) lze provádět Cčkovským printf. Vstup z terminálu realizuje funkce input, která vrátí první zadané číslo. K terminálové komunikaci slouží i další příkazy, viz původní dokumentaci.

K výpisu do souboru lze použít funkce fdisp nebo fprintf, přičemž je nutno soubor nejprve otevřít funkcí fopen a poté zavřít funkcí fclose. Podobné je i načítání z textového souboru – lze použít funkci fscanf (mající oproti C++ mírně odlišné argumenty – viz původní dokumentaci).

Grafický výstup

Chceme-li výsledky našich výpočtů vykreslit do grafu, není nic snadnějšího než použít funkci plot(x,y), kde x jsou data, která mají být zobrazena na vodorovné ose (možno vynechat) a y jsou data, která mají být zobrazena na svislé ose. Obojí mohou být jak vektory, tak i matice – podrobnosti najdete v původní dokumentaci. Graf takto vytvořený bude typický čárový.

Kromě čárového grafu lze vytvořit i graf sloupcový (funkce hist) nebo schodovitý (funkce stairs). Jinak můžeme vytvořit graf s jednou logaritmickou osou – k tomu slouží funkce semilogx a semilogy, graf s oběma osami logaritmickými (funkce loglog), graf v polárních souřadnicích (funkce polar), 3D síťový graf funkcí mesh, 3D barevný graf funkcí contour.

Chceme-li více grafů vložit do jednoho, tj. „malovat stále přes sebe“, stačí vykreslit první graf a pak zadat příkaz hold on. K ukončení kreslení přes sebe slouží příkaz hold off. Další možnosti, jak více grafů vložit do jednoho, najdete v původním manuálu.

Grafický výstup však Octave sám neprodukuje – používá k tomu GNUPLOT. Pro export obrázku do některého z vektorových formátů (fig, eps) použijte příkazy gset term a gset output a pak obrázek vyexportujte příkazemreplot (když již máte svůj graf vykreslen v okně), příklad použití je např. v původním manuálu. Pokud jste v GNUPLOTu zběhlí, bude lepší použít funkce gplot, resp. gsplot pro 2D, resp. 3D graf, které vám umožní zadávat graf přímo příkazy GNUPLOTu.

Funkce

V Octave je možné používat dávkové spouštění programů. Tyto programy mohou být buď skripty (několik příkazů pod sebou), nebo funkce. Rozdíl mezi skripty a funkcemi je stejný jako v jiných jazycích – funkce mají svůj lokální prostor proměnných (skripty nemohou žádné proměnné vracet, ale mohou zapisovat do proměnných přístupných zvnějšku). Práce s globálními proměnnými je tak trochu netypická – podrobnosti viz původní manuál. Nicméně, vracení proměnné z funkcí je jednoduché – každá funkce může vrátit jakýkoli počet proměnných jakéhokoli typu (a počet proměnných dokonce nemusí být specifikován, viz původní manuál). Pokud je návratových hodnot funkce více, je nutno je oddělit čárkou a celý seznam uzavřít do hranatých závorek. Stejně tak může být i proměnný počet argumentů funkce – viz původní manuál.

Pokud soubor (textový) nezačíná klíčovým slovem function (nebo komentářem, který je od znaku % do konce řádku), jde o skript. První řádek souboru s funkcí pak vypadá následovně: function vysledek = jmeno_funkce (argumenty), kde jmeno_funkce bývá shodné s názvem souboru (tyto textové soubory mají obvykle příponu .m) a spouští se ze shellu pod tímto jménem (pokud je k nim nastavená cesta (proměnné LOADPATH nebo DEFAULT_LOADPATH) nebo jsou v aktuálním adresáři). Argumenty funkce jsou odděleny čárkou. Konec funkce je označen klíčovým slovem endfunction, funkce vám však budou fungovat i bez něj. Jestliže funkce nemá žádné argumenty, nemusí se narozdíl od C++ za název funkce psát kulaté závorky. Na konci funkce se nepíše žádné return, jen je třeba zaručit, aby proměnné uvedené jako návratové hodnoty dostaly před ukončením funkce tu správnou hodnotu. Lze samozřejmě volat z jednoho souboru funkci, která je v souboru jiném.

Pokud chceme vykonávání funkce ukončit jinde než na konci (např. v nějaké podmínce, která odhalila chybu), použijeme příkaz return (bez parametrů). Návratové proměnné musejí mít v tuto chvíli definovanou nějakou hodnotu.

Zajímavou možností je dynamické linkování funkcí napsaných v C++. Pro nedostatek času se tím zde nebudeme zabývat a odkážeme na původní dokumentaci.

Další podrobnosti o funkcích jsou v původním manuálu a o funkcích v souborech jinde v původním manuálu.

Podmínky, cykly apod.

Začněme obyčejnou podmínkou if. Ta je stejná jako v jiných jazycích: vážou se k ní příkazy else a endif (možno nahradit pouhým end). Není zde žádné begin, blok začíná buď příkazem if, nebo else. Je možná i složitější konstrukce s použitím elseif – na tu odkazuji do původního manuálu.

Dalším příkazem je začátek cyklu while, za kterým následuje podmínka, pak tělo cyklu (opět bez begin) a nakonec endwhile (opět stačí obyčejné end). Další možností cyklení, stejně jako v jiných programovacích jazycích, je konečný cyklus for, za kterým následuje výraz (např. for i=1:10 znamená něco provést desetkrát) a za tělem cyklu endfor (nebo end). Cyklus for lze i použít pro cyklení přes prvky struktury – o tom více v původní dokumentaci. K řízení pohybu v cyklech slouží, podobně jako v jiných jazycích, příkazy break a continue.

Octave od verze 2.0.5 už zná i příkaz switch, který zde nebudeme rozebírat (velmi podobné C++) a zájemce odkáži na původní dokumentaci.

Programátoři snad uvítají, že Octave též poskytuje jakýsi jednoduchý systém ošetření výjimek. Bližší popis je v původním manuálu.

Základní statistické funkce

Udělejme reklamu také základním statistickým funkcím, jako jsou střední hodnota pole mean(a), kde a je ono jednorozměrné pole (je-li a pole dvourozměrné, bude výsledkem místo skaláru pole jednorozměrné) nebo standardní odchylka std(a), medián median(a), kvartily… Mezi nejpoužívanější patří maximum pole (v případě dvojrozměrného pole je výsledkem pole jednorozměrné, tj. pro výběr maximálního prvku matice je nutno operátor aplikovat dvakrát) max(a) a minimum min(a). Dodejme, že Octave má implementován velký počet statistických rozdělení – normální, binomické, exponenciální, Poissonovo, gamma, Cauchyovo, Studentovo, logaritmicko-normální a řadu dalších. U každého rozdělení existuje funkce na výpočet hodnoty distribuční funkce v daném bodě, kvantily a hustoty pravděpodobnosti. U každého rozdělení také existuje funkce, která podle daného rozdělení vygeneruje matici (vektor) hodnot.

CS24_early

Diferenciální rovnice

Numerické řešení (soustav) diferenciálních rovnic je již složitější záležitostí, kterou zde nebudu rozepisovat a případné zájemce odkáži na původní návod. Octave též umožňuje řešit soustavy algebraických a diferendiálních rovnic; návod k jejich řešení najdete tamtéž. Symbolické řešení čehokoli Octave, narozdíl od komerčních matematických programů, zatím neposkytuje.

Další funkce

Závěrem zmiňme několik dalších oborů, ke kterým má Octave co říci: patří mezi ně např. teorie řízení, konverze (a rozklad) obrazových a audio dat, zpracování signálů nebo optimalizace. Octave také obsahuje funkce pro práci s řetězci, s polynomy a financemi.

Byl pro vás článek přínosný?

Autor článku