Я пытаюсь сгенерировать случайный граф в форме списка смежности для генеративного тестирования. Пример графика будет:
{:a #{:a :b}, :b #{:a :b}}
(Списки смежности реализованы в виде наборов.)
Моя первая идея была такой:
(def vertex-gen (tcgen/fmap (comp keyword str) tcgen/char-alpha-numeric))
(def random-graph-gen-1
(tcgen/let [vertices (tcgen/set vertex-gen {:min-elements 1})]
(tcgen/map (tcgen/elements vertices)
(tcgen/set (tcgen/elements vertices)))))
({min-elements 1}
требуется, потому что tcgen/elements
не работает на пустых наборах.)
Тем не менее, это создает риск создания графиков, таких как
{:a #{:a :b}}
где :b
выбирается случайным образом для списка смежности :a
, но не выбирается для самого графа. Так что у :a
есть сосед, которого не существует.
Другой вариант -
(def random-graph-gen-2
(tcgen/let [vertices (tcgen/set vertex-gen)]
(->> vertices
(map #(->> vertices
(tcgen/elements)
(tcgen/set)
(tcgen/generate)
(vector %)))
(into {}))))
, который перебирает все вершины и явно генерирует случайный список смежности для каждой вершины. Это гарантирует, что все вершины появятся в графе, но имеет недостаток в том, что test.check не видит генерируемых списков смежности. Поэтому я беспокоюсь, что это испортит логику сокращения.
Есть ли решение, позволяющее избежать обеих этих ловушек?