Знайомство з graphviz

Знайомство з graphviz

Є в Юнікс така потрібна утиліта під назвою GraphViz, створена для малювання графів. У цьому пості я наведу приклад її використання. Тим, хто з ГрафВізом вже знаком, буде не цікаво, краще почитайте про Dracula.

Інших же, сподіваюся, цей пост підштовхне до більш уважного вивчення цієї програми.

Думка звичайна. Є конфиг (файл .gv), за допомогою якого дається опис графа. Конфиг цей приблизно такого змісту:

digraph G "A" -> "B";
"B" -> "C";
"A" -> "C";
>

GraphViz приймає такий конфіг на вході, а на виході дає png | jpg | gif | svg файл із зображенням графа. При бажанні можна дати більш докладний опис графа. Наприклад, вказати форму і колір вершин, товщину і спрямованість ребер і т.д ..

Зупинятися на цьому я не буду, в man-pages все детально розписано.

До складу GraphViz заходить кілька програм, які чомусь називаються «фільтрами». За допомогою їх один і той же граф можна намалювати різними методами. Перелік і короткий опис програм:

dot - filter for drawing directed graphs
neato - filter for drawing undirected graphs

twopi - filter for radial layouts of graphs

circo - filter for circular layout of graphs
fdp - filter for drawing undirected graphs
sfdp - filter for drawing large undirected graphs

Приклади графів, намальованих за допомогою їх, ви зможете подивитися на офіційному веб-сайті програми.

Давайте створимо вид, нібито ви почитали мани і погортали веб-сайт. Відмінно, зараз можна випробувати вирішити за допомогою графвіза якусь задачу.

Уявімо, що у нас є кілька компаній, а у цих компаній є клієнти. З якихось причин ми можемо відстежувати, до якої компанії звертається клієнт, якщо він відмовляється від послуг іншій компанії. У разі, скажімо, з хостингом, це справді легко зробити.

Завдання - вибудувати граф, який зображає переміщення клієнтів від компанії до компанії.

Ось скрипт, що генерує .gv файл:

use strict;
use List :: Util qw / max shuffle /;
use List :: MoreUtils qw / uniq /;
use DBI;
use constant MIN_PERCENT => 5;

# Генеруємо просто помітні і не дуже чорні кольори
my @colors;
for my $ c (qw / 8 D A Дев'ять F 6 /) for my $ m (qw / FF0000 00FF00 00FFFF FF00FF FFFF00 /) my $ t = $ m;
$ T =

# Забираємо дані з БД
my $ db = DBI-> connect (
"Dbi: mysql: database: localhost", "user", "password",
0, RaiseError => Нуль>
) Or die "ERROR: $! \ N";

my $ res = $ db-> prepare ($ query);
$ Res-> execute () or die "Query failed: \ n \ n $ query";

# Початок опису графа

Знайомство з graphviz

print "digraph G print qq nodesep = 2;
mindist = 2;
>;
print "\ n";

# Максимум клієнтів перейшло
my $ max_cnt = 1;

# Плюс і мінус число клієнтів для компанії
my% plus;
my% minus;

while (my ($ from, $ to, $ cnt) = $ res-> fetchrow_array ()) $ data = $ cnt;
$ Plus + = $ cnt;
$ Minus + = $ cnt;
$ Max_cnt = $ cnt> $ max_cnt. $ Cnt. $ Max_cnt;
push @sources, $ from;
push @sources, $ to;
>

# Shuffle для того, щоб можна було
# Перемалювати граф незначно по-іншому
@sources = shuffle uniq @sources;

Знайомство з graphviz

for my $ src (@sources) # відкидаємо компанії з маленькою "плинністю клієнтів"
next if (max ($ plus, $ minus) <$max_cnt*MIN_PERCENT/100);

# Беремо черговий колір
my $ color = $ colors [$ i ++];
my $ delta = $ plus - $ minus;
# Опис верхівки графа, відповідної компанії
print "" $ src "[label =" $ src \\ n + ". int ($ plus).", - ". int ($ minus).", delta: $ delta ", style =" filled ", fontcolor = "# 111111", color = "# $ color", ".
# Для тих, кому більше подобаються прямокутники :)
# "Shape =" box ", width = 4, height = 1,".
"Fontsize = 16]; \ n";
for my $ to (keys%>) my $ cnt = $ data;
my $ percents = $ cnt * 100 / $ max_cnt;
# Дуже "тонкі" дуги не виводиться
if ($ percents> MIN_PERCENT) # виводимо опис дуги
print "" $ src "->" $ to "[label =" $ cnt ", fontcolor =" # $ color ", color =" # $ color ", penwidth =". int (Один + $ percents * 12/100). ", Fontsize =". Int (12 + $ percents * 12/100). "]; \ N";
>
>
>
# Кінець опису графа
print "\ n> \ n";

Приклад gv-файлу, зробленого за допомогою цього скрипта, можна подивитися тут. Зрозуміло, що всі дані в ньому не справжні. Перетвориться GV в SVG наступним чином:

circo graph-fake.gv -Tsvg -o fake.svg

Тут можна завантажити придбаний граф. А кому лінь качати (або раптом у когось SVG не розкривається), ось картина набагато менше:

Знайомство з graphviz

Більшості пішли клієнтів відповідають більш товсті смуги. Крім того, кожній компанії відповідає власний колір.

Можна було б ще поміняти розмір вершин залежно від того, скільки всього нових клієнтів отримала компанія, але у мене щось не вийшло зробити це прекрасно. Може, у вас краще вийде.

Не так давно мені надійшов ще один лист від 1-го з читачів блогу. Творець листи нарікав, що на кафедрі, на якій він навчається, мало уваги приділяється програмування, також цікавився, чи не зн.

Найближчим часом я пару раз згадував про те, що ні зовсім розумію, як на Haskell можна розробляти справжні, величезні проекти. Тому було кілька причин, але головним чином мене турбує.

Найближчим часом я практично перестав грати в комп'ютерні ігри. Але іноді, коли необхідно знищити час, потреба в них з'являється. Є трохи ігор під UNIX, які мені справді подобається.

Redis (REmote DIctionary Server) - це нереляційних високопродуктивна СУБД. Redis зберігає всі дані в пам'яті, доступ до даних здійснюється по ключу. Опціонально копія даних може хранітьс.

Трохи раніше мені захотілося дуже звичайний речі - щоб при отриманні новітньої електронної пошти подекуди в кутку екрану виникало повідомлення про це. Притому мені потрібні були лише сповіщення.

Схожі статті