Есть ли библиотека для рисования структур деревьев состояний в TikZ?

Есть ли библиотека для рисования структур деревьев состояний в TikZ?

State tree structure (STS)s — это особый вид диаграмм, принадлежащий к state chartсемейству s.

Типичный пример STSможно изобразить следующим образом:

введите описание изображения здесь

Количество ветвей, государственных меток и символов креста или союза может быть сформировано в любую произвольную структуру по замыслу дизайнера.

Возможно, tikz-treesэто будет приближение, но, как я проверил, я не думаю, что он способен сгенерировать что-то похожее на эту цифру в целом.

Есть ли какая-нибудь специализированная библиотека для чего-то подобного TikZ?!

решение1

Вот версия, которая определяет стиль Forest, state treeдля форматирования деревьев этого типа. Предположения, основанные на примере, таковы:

  • дети должны быть распределены равномерно;
  • первый и последний дочерний элемент должны находиться на одинаковом расстоянии от родителя;
  • ребра следует рисовать только для первого и последнего потомка;
  • содержимое узлов должно быть набрано в математическом режиме.

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

Вот код для дерева, который представляет собой небольшую адаптациюИгнаси:

\begin{forest}
  state tree,
  [x_0
    [x_1
      [x_{11}
        [x_{111}]
        [\dot{\cup}]
        [x_{112}]
      ]
      [\times]
      [x_{12}
        [x_{121}]
        [\dot{\cup}]
        [x_{122}]
      ]
    ]
    [\dot{\cup}]
    [x_2]
    [\dot{\cup}]
    [x_3
      [x_{31}]
      [\dot{\cup}]
      [x_{32}]
      [\dot{\cup}]
      [x_{33}]
    ]
  ]
\end{forest}

state treeзадает стиль. Остальное происходит автоматически, поэтому нет необходимости в no edgeetc.

Это дает следующий результат:

дерево состояний

Полный код:

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
% ateb: addaswyd o ateb Ignasi: https://tex.stackexchange.com/a/351690/
\forestset{%
  state tree/.style={%
    for tree={
      math content,
      parent anchor=children,
      child anchor=parent,
      tier/.option=level,
      calign=center,
    },
    where={>On>{n children}{2}}{
      for nodewalk={
        filter={children}{>On=!On=!&{n}{1}{n'}{1}}
      }{no edge}
    }{},
    before computing xy={
      where={isodd(n_children)}{
        tempdima/.process={OOOw3+d{!n=1.s}{!n'=1.s}{n children}{(##2-##1)/(##3-1)}},
        tempdimb/.option={!n=1.s},
        for children={
          s/.process={RROw3+d{tempdima}{tempdimb}{n}{##2+(##1*(##3-1))}}
        },
      }{},
    },
  },
}
\begin{document}
\begin{forest}
  state tree,
  [x_0
    [x_1
      [x_{11}
        [x_{111}]
        [\dot{\cup}]
        [x_{112}]
      ]
      [\times]
      [x_{12}
        [x_{121}]
        [\dot{\cup}]
        [x_{122}]
      ]
    ]
    [\dot{\cup}]
    [x_2]
    [\dot{\cup}]
    [x_3
      [x_{31}]
      [\dot{\cup}]
      [x_{32}]
      [\dot{\cup}]
      [x_{33}]
    ]
  ]
\end{forest}
\end{document}

решение2

Вы также можете попробовать с forest, хотя я не знаю, как правильно распределить некоторых детей:

\documentclass [multi=forest, border=2mm]{standalone} 
\usepackage{forest}

\begin{document}
\begin{forest}
for tree={math content}
[x_0
    [x_1 
        [x_{11} 
            [x_{111}] 
            [\dot{\cup}, no edge] 
            [x_{112}]]
        [\times, no edge]
        [x_{12}
            [x_{121}]
            [\dot{\cup}, no edge]
            [x_{122}]]]
    [\dot{\cup}, no edge]
    [x_2, no edge]
    [\dot{\cup}, no edge]
    [x_3
        [x_{31}]
        [\dot{\cup}, no edge]
        [x_{32}, no edge]
        [\dot{\cup}, no edge]
        [x_{33}]]]
\end{forest}

\end{document}

введите описание изображения здесь

Обновление: с предложением JLDiaz результат выглядит лучше, все еще не идеально, но лучше.

\documentclass [multi=forest, border=2mm]{standalone} 
\usepackage{forest}

\begin{document}
\begin{forest}
for tree={math content}
[x_0
    [x_1 
        [x_{11} 
            [x_{111}] 
            [\dot{\cup}, no edge] 
            [x_{112}]]
        [\null, no edge]  %<-------------
        [\times, no edge]
        [x_{12}
            [x_{121}]
            [\dot{\cup}, no edge]
            [x_{122}]]]
    [\null, no edge]        %<-------------
    [\dot{\cup}, no edge]
    [x_2, no edge]
    [\dot{\cup}, no edge]
    [x_3
        [x_{31}]
        [\dot{\cup}, no edge]
        [x_{32}, no edge]
        [\dot{\cup}, no edge]
        [x_{33}]]]
\end{forest}

\end{document}

введите описание изображения здесь

решение3

Первая попытка будет следующей. Я не очень опытен в рисовании деревьев, так что, возможно, есть лучший способ сделать это. Однако, ключевым моментом является размещение узлов между потомками, и библиотека calcидеально подходит для этого:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}

\def\rootname{root}
\newcommand{\stnode}[3]{\node at ($(#1)!0.5!(#2)$) { #3 }}
\newcommand{\stnodec}[3]{\node at ($(#1.center)!0.5!(#2.center)$) { #3 }}
\newcommand{\stnoderootc}[3]{\node at ($(\rootname-#1.center)!0.5!(\rootname-#2.center)$) { #3 }}

\begin{document}
    \begin{tikzpicture}
        [
            level 1/.style = {sibling distance = 3cm},
            level 2/.style = {sibling distance = 2cm}
        ]
        \node (root) { $x_0$ }
            child { node { $x_1$ } 
                child { node { $x_3$ } }
                child { node { $x_4$ } }
            }
            child { node { $x_2$ } 
                child { node { $x_5$ } }
                child { node { $x_6$ } }
            }
        ;
        place the annotation nodes between the children
        \stnode{root-1.center}{root-2.center}{$\times$};
        \stnodec{root-1-1}{root-1-2}{$\times$};
        \stnoderootc{2-1}{2-2}{$\times$};
    \end{tikzpicture}
\end{document}

Вы можете использовать один из трех макросов ( \stnode, \stnodec(сenter), \stnoderootc(автоматический корневой узел, центр)) для размещения узлов аннотации. Имя корня должно быть переопределено, чтобы представлять фактическое имя корневого узла. Для максимальной гибкости просто используйте \stnode.

Аргументы: #1: первый узел, #2: второй узел, #3: текст узла.

Результат следующий: Результат

Очевидно, что соответствующие узлы должны иметь одинаковое расположение по оси Y. Если это не так, то это все равно будет работать, но выглядеть это будет странно.

Связанный контент