Сети PETRI

Сети петри для ознакомления с возможностями NODE и настройки своих стилей.

Установка необходимых библиотек для работы

\documentclass{article} % say

\usepackage{tikz}
\usetikzlibrary{arrows.meta,decorations.pathmorphing,backgrounds,positioning,fit,petri}

\begin{document}
\begin{tikzpicture}
  \draw (0,0) -- (1,1);
\end{tikzpicture}
\end{document}

Просто нарисуем в системе координат 5 node

\begin{tikzpicture}
  \path ( 0,2) node [shape=circle,draw] {}
        ( 0,1) node [shape=circle,draw] {}
        ( 0,0) node [shape=circle,draw] {}
        ( 1,1) node [shape=rectangle,draw] {}
        (-1,1) node [shape=rectangle,draw] {};
\end{tikzpicture}

Но, выяснилось, что вариант выше не очень умен по своей сути. \path задает координату откуда начинается какое-то действие, в нашем случае размещаем node, а можно draw, но node с параметром draw обернет текст рамкой.

Синтаксис at т.е. поместить в…

step1

\begin{tikzpicture}
  \path node at ( 0,2) [shape=circle,draw] {}
        node at ( 0,1) [shape=circle,draw] {}
        node at ( 0,0) [shape=circle,draw] {}
        node at ( 1,1) [shape=rectangle,draw] {}
        node at (-1,1) [shape=rectangle,draw] {};
\end{tikzpicture}

Получаем тотже эффект, но говорят умнее.

Дальше больше:

\begin{tikzpicture}
  \path node at ( 0,2) [circle,draw] {}
        node at ( 0,1) [circle,draw] {}
        node at ( 0,0) [circle,draw] {}
        node at ( 1,1) [rectangle,draw] {}
        node at (-1,1) [rectangle,draw] {};
\end{tikzpicture}

Прикручиваем стили

\begin{tikzpicture}[thick]
  \path  node at ( 0,2) [circle,draw=blue,fill=red] {}
         node at ( 0,1) [circle,draw=blue,fill=yellow] {}
         node at ( 0,0) [circle,draw=blue,fill=green] {}
         node at ( 1,1) [rectangle,draw=black!50,fill=black!20] {}
         node at (-1,1) [rectangle,draw=black!50,fill=black!20] {};
\end{tikzpicture}

step2 Причем [draw=blue] — рисует такого цвета обводку, а fill — заполняет пространство

А теперь сделаем стиль универсальным на блок

\begin{tikzpicture}
  [place/.style={circle,draw=blue!50,fill=blue!20,thick},
   transition/.style={rectangle,draw=black!50,fill=black!20,thick}]
  \node at ( 0,2) [place] {};
  \node at ( 0,1) [place] {};
  \node at ( 0,0) [place] {};
  \node at ( 1,1) [transition] {};
  \node at (-1,1) [transition] {};
\end{tikzpicture}

просто один будет называться place а второй transition и теперь название этихстилей ставим в описании node.

Размеры SHAPE

Можно задать переменную inner sep=2mm в блоке — и это сделает отступ вокруг текста 2mm. Или:

[place/.style={circle,draw=blue!50,fill=blue!20,thick,
                 inner sep=0pt,minimum size=6mm},

т.е прямо в стиль и это даст эффект, что размер будет не меньше 4мм, пока в него влезает текст.

step3

Имена SHAPEs

Очень пригодятся имена SHAPEs для того,чтобы иметь привязки и потом на них ссылаться.

\begin{tikzpicture}
  \node (waiting 1)      at ( 0,2) [place] {};
  \node (critical 1)     at ( 0,1) [place] {};
  \node (semaphore)      at ( 0,0) [place] {};
  \node (leave critical) at ( 1,1) [transition] {};
  \node (enter critical) at (-1,1) [transition] {};
\end{tikzpicture}

имена будут в круглых скобочках, причем порядок написания не имеет значения. Это все определения одного \path

Нативное размещение SHAPEs

Вместо указания координат, можно указывать влево, вправо, ниже, выше. Такого ума можно набраться в библиотеке: \usetikzlibrary {positioning}

\usetikzlibrary {positioning}
\begin{tikzpicture}
  \node[place]      (waiting)                            {};
  \node[place]      (critical)       [below=of waiting]  {}; % ниже waitinig
  \node[place]      (semaphore)      [below=of critical] {}; % ниже critical
  \node[transition] (leave critical) [right=of critical] {}; % справа от critical
  \node[transition] (enter critical) [left=of critical]  {}; % слева от critical
\end{tikzpicture}

Объекты размещаются по координатной сетке.

Метки объектов по сторонам света

Все объекты TIKZ получают метки по сторонам света:

  • north
  • south
  • west
  • east
  • north east
  • north west
  • south east
  • south west
 \node [red,above] at (semaphore.north) {$s\le 3$};
\end{tikzpicture}

напишет node красного цвета red над above северной меткой объекта semaphore.

но в библиотеке есть вариант с label, который сделает тоже самое.

  \node[place] (semaphore) [below=of critical, 
                             label=above:$s\le3$] {};

Памятка, как label работает:

\tikz
  \node [circle,draw,label=60:$60^\circ$,label=below:$-90^\circ$] {my circle};

step4

И немного подольем красочки: label={[red]below:$-90^\circ$} и будет метка красная, но чтобы небыло конфлика поставим все это дело в {}.

Коннекторы это просто

  \draw [->] (enter critical.east) -- (critical.west);
  \draw [->] (waiting.west) .. controls +(left:5mm) and +(up:5mm)
                            .. (enter critical.north);

т.е. \draw [в какую сторону стрелу] (координата откуда) -- (координата куда);

Краткий комментарий к .. CONTROLS ..

Это вставка вместо оператора рисования - -, которая позволяет поставить несколько контрольных точек относительно некоторого центра вращения и сказать куда они сдвигаются и насколько:

\draw[->](waiting.west) ..controls +(left:15mm) and +(up:15mm) .. (enter critical.north);

step5

Умность библиотеки tirz

Можно не указывать стороны света в метках, от сделает это автоматически

  \draw [->] (enter critical) -- (critical);
  \draw [->] (waiting) .. controls +(left:5mm) and +(up:5mm)
                            .. (enter critical);

будет тоже самое.

Совершенствуем стрелочки до предела (to [in out])

Замечательный оператор to, который укажет под каким углом выйти и под каким углом войти стрелке.

Схема такая же, только вместо наших - - и .. controls .. появляется еще один оператор to [out=,in=]

in=220 — выглядит еще причудлевее.

\draw[->](waiting) to [out=0, in=180] (leave critical)

step6

Команда bend right left

изгиб кривой.

\draw[->](leave critical) to [bend left=150] (semaphore)

step7

но лучше загибать bend left=45, правда лучше.

Теперь еще один элемент EDGE

край - ребро, как угодно, но эта штука действует как внутри \path так и самостоятельно. Т.е. можно задавать свои особые наконечники и цвета для edge.

 \node[transition] (enter critical) [left=of critical]  {}
    edge [->]               (critical)
    edge [<-,bend left=45]  (waiting)
    edge [->,bend right=45] (semaphore);

буквально: там где нарисовал node от неё начинаю рисовать edges.

  • не завершая node точкой с запятой пишем edge
  • [здесь команды куда стрела, как гнуть]
  • (куда соединяем)
  • теперь текущая точка опять в пункте node
  • продолжаем рисовать дальше от той же точки

Вот такой казус может получиться:

\begin{tikzpicture}
  \node (c) at (0,0) {};
  \node (n) at (0,1) {}
  edge [bend right=45] (w);
  \node (s) at (0,-1) {}
  edge [bend right=45] (e);
  \node (w) at (-1,0) {}
  edge [bend right=45] (s);
  \node (e) at (1,0) {}
   edge [->,bend right=45] (n);
\end{tikzpicture}

step8

Но если рисовать по задумке:

\begin{tikzpicture}
  \node (c) at (0,0) {};
  \node (n) at (0,1) {};
  \node (w) at (-1,0) {}
  edge [bend left=45] (n);
  \node (s) at (0,-1) {}
  edge [bend left=45] (w);
  \node (e) at (1,0) {}
   edge [bend left=45] (s)
   edge [bend right=45] (n);
\end{tikzpicture}

то получим -> step9

И все это упакуем в стили

  [bend angle=45,
   pre/.style={<-,shorten <=1pt,>={Stealth[round]},semithick},
   post/.style={->,shorten >=1pt,>={Stealth[round]},semithick}]

вот такая штука позволит дальше в коде писать просто:

edge [pre] (critical) и edge [post,bend right] (waiting) и TIKZ все поймет.

Метки на линиях

\begin{tikzpicture}[auto,bend right]
  \node (a) at (0:1) {$0^\circ$};
  \node (b) at (120:1) {$120^\circ$};
  \node (c) at (240:1) {$240^\circ$};

  \draw (a) to node {1} node [swap] {1'} (b)
        (b) to node {2} node [swap] {2'} (c)
        (c) to node {3} node [swap] {3'} (a);
\end{tikzpicture}

step10

  • NODE — нарисовали метки в узлах через оператор at, т.е. поместить в … конкретную точку
  • DRAW — рисует через оператор to, т.е. от одной точки к другой, а на пути его рисования мы размещаем другие NODE и говорим с какой стороны их рисовать относительно линии.
  • SWAP — это нарисовать зеркально
  • на пути DRAW, NODEs может быть сколько угодно, главное их всех разместить правильно, а то все в одну точку вляпаются.

Декоративные линии (\usetikzlibrary {decorations.pathmorphing})

Собственно любую линию можно нарисовать, просто отдельно нужно изучить особенности этой библиотеки.

\usetikzlibrary {decorations.pathmorphing}
\begin{tikzpicture}
  \draw [->,decorate,
     decoration={snake,amplitude=.4mm,segment length=2mm,post length=1mm}]
    (0,0) -- (3,0);
\end{tikzpicture}

получится вот такая кривулина: step11

И продолжая тему кривулины или любой другой линии, если мне нужно разместить текст, то делаю в разрыве DRAW вставку NODE:

node [above,text width=3cm,align=center,midway]
    {
      replacement of the \textcolor{red}{capacity} by
      \textcolor{red}{two places}
    }
  • above — выше над линией
  • text width=3cm — ширина текста 3см
  • align-center — текст выравнять по центру
  • midway — в центре линии (у него еще есть братья:
    • near start — pos=0.25.
    • near end — pos=0.75.
    • very near start — pos=0.125.
    • very near end — pos=0.875.
    • at start — pos=0.
    • at end — pos=1

BACKGROUND или слои и фон под картинкой

Нам поможет библиотека fit и background

fit — дает координаты всех узлов background — размещает на разных слоях рисунки

Еще нам понадобятся знания об окружении SCOPE — это просто окружение чего-то, такие своеобразные скобки, в которых будут действовать правила, которые мы установим, а за пределами SCOPE все возвращается в исходные установки.

\begin{tikzpicture}[ultra thick]
  \begin{scope}[red]
    \draw (0mm,10mm) -- (10mm,10mm);
    \draw (0mm,8mm) -- (10mm,8mm);
  \end{scope}
  \draw (0mm,6mm) -- (10mm,6mm);
  \begin{scope}[green]
    \draw (0mm,4mm) -- (10mm,4mm);
    \draw (0mm,2mm) -- (10mm,2mm);
    \draw[blue] (0mm,0mm) -- (10mm,0mm);
  \end{scope}
\end{tikzpicture}

этот пример на линиях все показал step12

а про background мы просто добавим в конце такой код:

 \begin{scope}[on background layer]
    \node [fill=black!30,fit=(waiting) (critical) (semaphore)
             (leave critical) (enter critical)] {};
  \end{scope}
  • on background layer — на каком слое разместить, т.е. под рисунком
  • \node — рисуем node
  • fill — заполняем ее цветом
  • fit — перечисляем все внутренние node по которым определяем координаты

Настройки стандартных библиотек для рисования сетей PETRI

\begin{tikzpicture}
  [node distance=1.3cm,on grid,>={Stealth[round]},bend angle=45,auto,
   every place/.style= {minimum size=6mm,thick,draw=blue!75,fill=blue!20},
   every transition/.style={thick,draw=black!75,fill=black!20},
   red place/.style= {place,draw=red!75,fill=red!20},
   every label/.style= {red}]

т.е. там уже все определено, поэтому нарисуем все, что уже пытались с использованием библиотеки:

\usetikzlibrary {arrows.meta,petri,positioning}
   \node [place,tokens=1] (w1)                                    {};
   \node [place]          (c1) [below=of w1]                      {};
   \node [place]          (s)  [below=of c1,label=above:$s\le 3$] {};
   \node [place]          (c2) [below=of s]                       {};
   \node [place,tokens=1] (w2) [below=of c2]                      {};

   \node [transition] (e1) [left=of c1] {}
     edge [pre,bend left]                  (w1)
     edge [post,bend right]                (s)
     edge [post]                           (c1);
   \node [transition] (e2) [left=of c2] {}
     edge [pre,bend right]                 (w2)
     edge [post,bend left]                 (s)
     edge [post]                           (c2);
   \node [transition] (l1) [right=of c1] {}
     edge [pre]                            (c1)
     edge [pre,bend left]                  (s)
     edge [post,bend right] node[swap] {2} (w1);
   \node [transition] (l2) [right=of c2] {}
     edge [pre]                            (c2)
     edge [pre,bend right]                 (s)
     edge [post,bend left]  node {2}       (w2);

а это ее более кудрявый друг:

\usetikzlibrary {arrows.meta,petri,positioning}
 \begin{scope}[xshift=6cm]
   \node [place,tokens=1]     (w1')                            {};
   \node [place]              (c1') [below=of w1']             {};
   \node [red place]          (s1') [below=of c1',xshift=-5mm]
           [label=left:$s$]                                    {};
   \node [red place,tokens=3] (s2') [below=of c1',xshift=5mm]
           [label=right:$\bar s$]                              {};
   \node [place]              (c2') [below=of s1',xshift=5mm]  {};
   \node [place,tokens=1]     (w2') [below=of c2']             {};

   \node [transition] (e1') [left=of c1'] {}
     edge [pre,bend left]                  (w1')
     edge [post]                           (s1')
     edge [pre]                            (s2')
     edge [post]                           (c1');
   \node [transition] (e2') [left=of c2'] {}
     edge [pre,bend right]                 (w2')
     edge [post]                           (s1')
     edge [pre]                            (s2')
     edge [post]                           (c2');
   \node [transition] (l1') [right=of c1'] {}
     edge [pre]                            (c1')
     edge [pre]                            (s1')
     edge [post]                           (s2')
     edge [post,bend right] node[swap] {2} (w1');
   \node [transition] (l2') [right=of c2'] {}
     edge [pre]                            (c2')
     edge [pre]                            (s1')
     edge [post]                           (s2')
     edge [post,bend left]  node {2}       (w2');
 \end{scope}

и на финише фон:

  \begin{scope}[on background layer]
    \node (r1) [fill=black!10,rounded corners,fit=(w1)(w2)(e1)(e2)(l1)(l2)] {};
    \node (r2) [fill=black!10,rounded corners,fit=(w1')(w2')(e1')(e2')(l1')(l2')] {};
  \end{scope}

  \draw [shorten >=1mm,->,thick,decorate,
         decoration={snake,amplitude=.4mm,segment length=2mm,
                     pre=moveto,pre length=1mm,post length=2mm}]
    (r1) -- (r2) node [above=1mm,midway,text width=3cm,align=center]
      {replacement of the \textcolor{red}{capacity} by \textcolor{red}{two places}};
\end{tikzpicture}

получим такую красоту:

step13