přejít na obsah přejít na navigaci

Linux E X P R E S, Gnuplot: Generujte grafy přímo z vašeho programu

Gnuplot: Generujte grafy přímo z vašeho programu

sinus.png

Gnuplot je jednou z nejznámějších aplikací pro tvorbu grafů ve dvou a třech dimenzích. Článek předkládá komplexnější ukázku, která demonstruje spolupráci gnuplotu, Pythonu a Bashe. Gnuplot bude vykreslovat úspěšnost genetického algoritmu pro řešení Sudoku.


Gnuplot vykresluje data ze souborů, bodů zadaných uživatelem, funkcí zadaných předpisem nebo gnuplotem spočtených proložených dat funkcí (fit). Gnuplot je konzolová aplikace ovládána textovými příkazy. Mezi nejfrekventovanější elementy jazyka gnuplotu patří:

  • Nejzákladnější klíčové slovo plot provádí vykreslení grafu.

  • Matematické formule se zadávají podobně jako v programovacím jazyku C/C++. Například zápis x**2 vyjadřuje čtverec proměnné x.

  • Řetězce se deklarují uvozovkami.

  • Klíčové slovo set zajišťuje nejrůznější nastavení.

  • Při zadání výrazu save se uloží do spustitelného skriptu poslední kreslicí příkaz a nastavení prostředí. Spuštěním skriptu se provede plotovací příkaz s uloženými nastaveními.

  • Znak otazník (nebo synonymní klíčové slovo help) s uvedeným výrazem zobrazí příslušnou nápovědu.

  • Znak vykřičník vynutí interpretaci zbytku řádky jako příkazu Bashe. Uživatel je tak s to pracovat v terminálu přímo z gnuplotu.

Graf funkce sin(1/x) Graf funkce sin(1/x)

Chtějme pro osvětlení způsobu práce v gnuplotu připravit třeba graf funkce sin(1/x). V řádkovém rozhraní gnuplotu stačí zadat pouze příkaz plot sin(1/x). Graf se otevře ve vlastním okně, které vidíte na předcházejícím obrázku.

Týž graf se zjemněným vzorkováním Týž graf se zjemněným vzorkováním

Zjevně v důsledku přílišné hrubosti graf nerespektuje průběh funkce v oblasti druhého překmitu. Počet interpolačních bodů zvýším na 5000 příkazem set sample 5000. Překreslení příkazem plot sin(1/x) očividně zlepšilo graf.

Další vylepšení grafu Další vylepšení grafu

Nyní popíši graf, přikreslím funkci druhé mocniny a omezím definiční obor na jednotkové okolí nuly. Nadpis grafu zajistí příkaz set title "Dvě funkce". Graf vytvořím příkazem plot [-1:1] sin(1/x) title "první funkce", x*x title "druhá funkce".

Podobným aditivním postupem by šlo graf dále vylepšovat. O přístupné funkcionalitě poskytne představu oficiální galerie a v ní zveřejněné skripty korespondujícími s grafy. Nad to existuje množství volně dostupných tutoriálů a dokumentace ke gnuplotu.

Další nasazení gnuplotu

Výše uvedené „přímé deklarace“ neodráží nejběžnější způsob práce v gnuplotu. Gnuplot totiž není obvykle využíváván přímo, ale tvoří součást jiných řešení. Gnuplot se nasazuje jako vykreslovací engine u mnoha prominentních projektů. Textově orientované rozhraní gnuplotu totiž představuje z hlediska programátora jasnou konkurenční výhodu oproti převážně grafickým systémům (např. QtiPlot). S jistou nadsázkou by šlo třeba Octave označit za frontend ke gnuplotu. Máte-li nainstalované některé matematické aplikace, pravděpodobně budete mít nainstalovaný i gnuplot.

Gnuplot v Octave Gnuplot v Octave

Navzdory svému názvu gnuplot nesouvisí s aktivitami hnutí GNU. První tři písmena se proto v názvu gnuplot záměrně píší malými písmeny, aby se naznačila odlišnost od produktů GNU. Licence gnuplotu se shoduje, až na jedno podstatné omezení, s běžnými svobodnými licencemi. Smluvní ustanovení totiž vylučuje prosté šíření děl odvozených od gnuplotu. Rozšíření gnuplotu musí být šířena výhradně izolovaně od samotného gnuplotu ve formě rozdílových patchů zdrojového kódu. Gnuplot nerespektuje právo spotřebitele šířit odvozená díla, a proto patří do nepříliš početné kategorie nesvobodného open source. Svobodné náhrady gnuplotu (např. PLPlot a Grace) se těší znatelně nižší popularitě.

Při vývoji softwaru lze gnuplot využít různými způsoby. Například gnuplot může pro webovou aplikaci dynamicky generovat grafy. Stačí jej jen doinstalovat do LAMP serveru. Zbytek článku studuje návrh možného programátorského využití gnuplotu. Pro další výklad si zvolme následující úlohu:

  • Implementujme skript pro řešení číselné křížovky Sudoku metodou genetického algoritmu.

  • Pravděpodobnostní charakter algoritmu vyžaduje mnohonásobné provádění simulace. Statistická chyba totiž v asymptotě klesá jen se čtvercem počtu měření.

  • V gnuplotu vykreslíme rychlost konvergence při různých parametrech algoritmu. Vzhledem k výpočetní intenzivnosti úlohy (řádově hodiny) chceme tento krok provést bez interakce s uživatelem.

  • Grafy se rovněž automaticky uloží. Případně výsledky rozešlete svým přátelům utilitou mailutils.

Popis ukázkového skriptu v Pythonu

Zdrojový kód řešitele Sudoku Zdrojový kód řešitele Sudoku

Díky extrémně efektivním syntaktickým konstrukcím jazyka Python se celý řešitel vešel do méně než třiceti řádků zdrojového kódu. Krom toho jsem Python vybral, protože se jedná o skriptovací jazyk hojně používaný v matematice. Ačkoli v Pythonu existují řešení s přímou podporou gnuplotu, zvolil jsem v dalším výkladu univerzálně platný postup využívající prostředků samotného operačního systému.

Pravidla Sudoku kladou podmínky na vyplnění sloupců, řádků a čtverečků. Například jednou z podmínek je, že třetí řádek musí obsahovat sedmičku. Tuto vazbu program ukládá jako řetězec „radek37“ do proměnné constrains. Pravidla se testují v řádcích číslo 8, 9 a 10. Poslední řádek funkce fitness vrátí počet splněných podmínek. Nejvyšší teoreticky možná hodnota 243 funkce fitness odpovídá splnění všech podmínek, což je pochopitelně ekvivalentní korektnímu vyplnění křížovky Sudoku. Genetický algoritmus řeší úlohu jako optimalizační úlohu maximalizace funkce fitness.

Z populace se nevyřazují nejlepší vygenerované prvky, a proto se průměrné zdraví populace v okamžiku po selekci monotónně zvyšuje. Po dostatečně dlouhém čase budou populaci tvořit prvky s maximálním zdravím, které řeší úlohu. Naopak vyřazování nejlepších prvků by řešilo úlohu nalezení nejhoršího možného vyplnění, což by představovalo analogii například šachové výzvě samomatu.

Vlastní logika programu funguje následovně: Algoritmus provede vytvoření mutace zcela náhodným doplněním nezadaných polí (řádek 21). Následně generuje nové prvky křížením prvků v populaci (řádek 24). Při dosažení limitní velikosti populace se nejhorší prvky zahodí (řádek 18). Iterace popsané v tomto odstavci se mnohokrát opakuje.

K vytvoření zadání (řádek 21 zdrojového kódu) posloužil program kSudoku, který se dostal mezi základní hry prostředí KDE.

Přístup ke gnuplotu skrze Bash

Operační systém Linux připouští několik způsobů spuštění programu:

  • Forkování rozdělí proces na dva nezávislé stejné procesy. Bohužel fork nespouští libovolný kód, takže z vašeho programu nespustí gnuplot.

  • Eval nahradí kód původního procesu jiným kódem, takže místo zbytku programu začne vykonávat jiný program.

  • Volání system vykoná zadaný příkaz v Bashi. Toto volání budu dále rozebírat.

Skript importuje požadované prostředky operačního systému jednoduše jako import os. Příkaz Bashe spouštějící gnuplot se nyní provede jednoduše řádkem os.system("gnuplot"). Často se vyskytuje velmi naivní blud, že Bash je primitivní jako DOS. Mezi vymoženosti Bashe patří třeba:

  • Středník řadí spouštění příkazů do série. Například sleep 10; scrot počká deset vteřin a následně sejme screenshot obrazovky.

  • Ampersand (znak &) spustí příkaz na pozadí. Takto se dají snadno spouštět další procesy paralelně.

  • Svislítko (znak |) propojí standardní výstup programu se standardním vstupem následujícího programu.

  • Znak „větší než“ (>) přesměruje standardní výstup do souboru.

Následující čtyři příklady rozvíjejí předcházející seznam na konkrétních příkladech:

  • Příkaz chmod +x skript_gnuplotu; ./skript_gnuplotu přidá souboru skript_gnuplotu právo na spuštění a spustí jej. (Připomínám, že v gnuplotu příkaz save uloží postup pro vykreslení posledního grafu a použitá nastavení.)

  • Po obměně příkazu na ./skript_gnuplotu & již skript nečeká na konec gnuplotu. Skript pokračuje s vykreslujícím gnuplotem souběžně.

  • Příkaz echo plot x**3 | gnuplot nechá gnuplot vykreslit třetí mocninu. Bohužel okno s grafem se hned spolu s gnuplotem zavře. Přepínač persist v echo plot x**3 | gnuplot -persist způsobí, že okno s grafem přežije svůj gnuplot.

  • Rozeberme komplikovanější příkaz echo -e "set terminal png \n plot x**3" | gnuplot > mocnina.png. Nejprve se v gnuplotu nastaví výstupní formát png (set terminal png), následně se vykreslí graf znázorňující průběh třetí mocniny a nakonec se finální graf ve formátu png pošle na standardní výstup, který Bash přesměruje do souboru mocnina.png. Téhož efektu lze neelegantně docílit explicitním nastavením výstupu přímo v gnuplotu echo -e "set terminal png \n set output \"mocnina.png\" \n plot x**3" | gnuplot.

Více o úžasných vlastnostech Bashe se dozvíte v našem seriálu.

Finální graf Finální graf

Do skriptu řešitele Sudoku jsem připsal část logující údaje o času a zdraví populace do csv souborů. Další připsaná část kódu mění podíl náhodných dat (poměr proměnných velikost_populace_min a pocet_mutací), pro každé jedno nastavení provede simulací tisíc a v závěru uloží vždy do samostatného souboru údaje o průměrném zdraví populace. Na závěr kódu jsem skrze os.system postupně zavolal v gnuplotu příkazy:

set key right bottom title "Podíl náhodných mutací :"
set xlabel "Počet iterací"
set ylabel "Průměrné fitness"
plot "ran005.csv" with lines title "5%" "ran01.csv" with lines title "10%", "ran02.csv" with lines title "20%"

Výsledek přiloženého kódu Výsledek přiloženého kódu

Výsledný graf je vidět výše. Doprovodná funkční ukázka se spokojuje pouze s jednou simulaci pro tisíc iterací, čímž se snižuje čas běhu na přijatelný řád vteřin. V ostatních ohledech se ukázka schoduje s popsaným skriptem. Příklad vygenerovaného výstupu skriptu je uveden na předchozím obrázku.

Dokument typu py

sudoku.py

Dokument typu py | Velikost 3,21 kB

Nahoru

Příspěvky

Tomáš Crhonek Gnuplot: Generujte grafy přímo z vašeho programu
Tomáš Crhonek 20. 03. 2012, 10:51:11
Odpovědět  Odkaz 
Skvělý článek. Není to tak dlouho, co jsem řešil grafování nějakých hodnot z DB právě pomocí gnuplotu. Tenhle článek pěkně dokazuje pravdivost unixové koncepce "dělej jednu věc a dělej ji pořádně" na triviálním spojení bashe, pythonu a gnuplotu do funkčního celku.

+1
Gnuplot: Generujte grafy přímo z vašeho programu
Mihi 20. 03. 2012, 16:37:01
Odpovědět  Odkaz 
Moc pěkné, s gnuplot jsem už párkráte koketoval, ale nijak moc mě nezaujal (potřeboval jsem vykreslit odezvu systému, Laplaceova transformace, atp.).

Kombinace s Pythonem se mi opravdu moc líbí. S tímto programovacím jazykem se budu muset více seznámit... :)

Díky za pěkný a zajímavý článek.
Gnuplot: Generujte grafy přímo z vašeho programu
antaresin 22. 03. 2012, 16:01:24
Odpovědět  Odkaz 
WOW ! Perfektní článek. To není jenom pro přečtení - to si nastuduju :)

Odpovědět

Nejsou podporovány žádné značky, komentáře jsou jen čistě textové. Více o diskuzích a pravidlech najdete v nápovědě.
Diskuzi můžete sledovat pomocí RSS kanálu rss



 
 

Top články z OpenOffice.cz