Элегантная реализация графа факториального дерева

Elegant Implementation Factorial Tree Graph



Решение:

Обновление 3: ExpressionGraph теперь доступен в версии 12.1.

Обновление 2: более оптимизированная версия для 2D-графиков:



ClearAll [g] g = GraphComputation`ExpressionGraph [ConstantArray [x, #], VertexLabels -> None] &;

Примеры:



g [Диапазон [2, 4]]

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



SetProperty [g [{3, 1, 3, 1, 2, 1, 4}], {GraphLayout -> 'RadialEmbedding', EdgeShapeFunction -> 'Line'}]

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

Оригинальный ответ:

ClearAll [f] f [g_: Graph] [n_List, o: OptionsPattern []]: = g [UndirectedEdge @@@ [email protected] GraphComputation`ExpressionGraph [ConstantArray [x, n]], o, GraphLayout -> {' BalloonEmbedding '}, ImageSize -> Large] f [g_: Graph] [n_Integer, o: OptionsPattern []]: = f [g] [Range [2, n], o]

Примеры:



f [] [6]

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

f [] [6, GraphLayout -> {'RadialEmbedding'}]

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

g1 = f [Graph3D] [6]

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

g2 = f [Graph3D] [6, GraphLayout -> {'RadialEmbedding'}]

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

Используйте список для количества вершин на каждом слое в качестве аргумента:

f [] [{3, 5, 2, 4}, GraphLayout -> {'RadialEmbedding', 'LayerSizeFunction' -> (# &)}]

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

Обновлять: ... взять Graph3D и как-то улучшить компоновку на высоких слоях: кажется, много потраченного впустую места.

Один из способов изменить пропорции прямоугольников без искажения формы вершин - это изменить размерVertexCoordinates с использованиемScalingTransform:

SetProperty [g1, VertexCoordinates -> ScalingTransform [{1, 1, 3}] [[электронная почта защищена]]]

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

SetProperty [g2, VertexCoordinates -> ScalingTransform [{1, 1, 3}] [[электронная почта защищена]]]

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

Или добавьте подопциюLayerSizeFunction в«Радиальное вложение»:

g3 = f [Graph3D] [6, GraphLayout -> {'RadialEmbedding', 'LayerSizeFunction' -> (# &)}]; SetProperty [g3, VertexCoordinates -> ScalingTransform [{1, 1, -3}] [[электронная почта защищена]]]

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

SetProperty [#, VertexCoordinates -> ScalingTransform [{1, 1, 3}] [[защита электронной почты] #]] & @ f [Graph3D] [{3, 5, 2, 4}, GraphLayout -> {'RadialEmbedding', 'LayerSizeFunction' -> (# &)}]

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


IGraph / M уже имеет это встроенное какIGSymmetricTree. Вы можете указать количество веток на каждом уровне.

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

IGSymmetricTree [Диапазон [2, 4], DirectedEdges -> True, GraphLayout -> 'LayeredEmbedding']

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

Реализация в основном написана на C (не в Mathematica), а не в igraph. Это просто проще реализовать процедурно, для чего хорошо подходит C. Вот почему я не делал этого в чистом WL.

Вот еще одна структура с разным количеством ветвей на каждом уровне.

IGSymmetricTree [{5, 4, 3, 2}]

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


вот моя элегантная реализация

l [c _]: = TakeList [[электронная почта защищена] [k!, {k, c}], [электронная почта защищена]!] [[c-1]]; T [x _]: = График [(F = Flatten) @Table [MapThread [# -> # 2 &, {[email protected] @Table [[email protected], i], l [i + 1]}], { i, 2, x + 1}]]; [электронная почта защищена]

который возвращается

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

но если ваша версия Mathematica не поддерживаетTakeList вот еще один способ

s [x_]: = Сумма [k!, {k, x}]; z [y_]: = Раздел [Диапазон [[защита электронной почты] + 1, s [y + 1]], 1 + y]; v [n_]: = Таблица [{Сгладить [z [n-1]] [[i]] -> z [n] [[i, j]]}, {i, n!}, {j, n + 1}]; дерево [t_]: = График [Flatten [Array [[email protected] # &, t], 3]]; [электронная почта защищена]

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

[электронная почта защищена]

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