Как я могу гарантировать, что DAG останется ацикличной после вставки node?

У меня есть DAG, сохраняющая связь между некоторыми объектами в моем приложении. Когда эта структура обновляется путем добавления новой вершины ниже существующей (т.е. Неявного создания нового ребра в новую вершину), а затем (в любое другое время) нового края оттуда к другим вершинам, я хочу убедиться, что график остается DAG, т.е. е. что мой код не создает циклы.

Должен ли я добавить обнаружение цикла для каждой операции вставки и подключения, или есть правила, которые я могу выполнить при вставке, что гарантирует что я не производю циклы?

Один из подходов, который я могу придумать, - сохранить топологический уровень каждого node и разрешить только новые ребра, указывающие на более высокие уровни (дальше от исходных узлов). Однако кажется, что это фактически лишит меня большой гибкости, которую я надеялся достичь, используя DAG вместо набора обычных деревьев.

Ответ 1

Вы также можете сохранить обратные ссылки и просто проверить, что конечная точка node добавляемого края не отображается ни в одном из родительских узлов источника node. Это будет быстрее, чем полное обнаружение цикла. По сути, это был бы алгоритм кратчайшего пути по обратным ссылкам, который для DAG должен быть линейной.

Как отмечает @Markus, если вы не создаете ссылки на и из нового node на существующие узлы, вы не сможете создать цикл, введя в график новый node.

Ответ 2

Когда эта структура обновляется добавлением новой вершины, а затем новым краем от нее к другим вершинам

Если все новые ребра из новой вершины, вы никогда не создадите циклы.

Если вы также собираетесь добавлять ребра в новую вершину из старых узлов, ваши параметры зависят от ожидаемой формы графика. Все они сводятся к вариациям частичного заказа, но есть хаки, которые дают лучшую производительность для деревьев, лесов, алмазных сеток и т.д. Что вы знаете о ожидаемой общей форме графа?

Ответ 3

В в этой статье существует онлайн-алгоритм для поддержания топологического упорядочения (стр. 4).

Ответ 4

Что вы можете сделать, так это сохранить упорядоченные узлы в топологическом порядке (поиск "топологической сортировки" ). Когда вы добавляете дугу из младшего порядка в более высокий node, вы знаете, что цикл не был создан. В обратном случае вам необходимо постепенно обновлять топологическое упорядочение и в то же время проверять цикл цикла.