2015-01-06 3 views
1

Я пытаюсь перечислить все возможные DAG с n вершинами. Я знаю, что их много, и я предполагаю, что n очень маленький (от 3 до 5). Мне было интересно, есть ли способ их перечислить. Мое начальное решение - создать их по количеству ребер m. Рассматривая структуры с 0 ребрами, то те с 1 ... и т. Д. Случаи m=0 или m=n(n-1)/2 являются исследованиями скважин (1 и n! соответственно). Однако мне непонятно, сколько DAG существует с краями 1<m<n(n-1)/2.Создание всех возможных направленных ациклических графов

Обновление: Как некоторые пользователи считают это широкой темой, я попытаюсь сузить ее до создания неориентированных графов. Поскольку для заданного ненаправленного графа G с границами m существуют 2^|m| ориентации, и я применил метод для этого, проверяя ацикличность. Вопрос по-другому: Как сгенерировать все возможные неориентированные графики для n вершин?

+0

downvoters: пожалуйста, посоветуйте мне, как это сделать более конкретным! – Xline

+0

Это больше похоже на проблему с математикой, чем на проблему с кодированием. – immibis

+1

@immibis IT - проблема кодирования. Независимо от того, сколько DAG существует, проблема заключается в том, как сгенерировать их в коде. – Xline

ответ

0

Там должен быть решением ДФСА к задаче создания графики, что-то вроде:

graph(g) { // g is current graph; start with an empty graph 
    find set V of vertices in g 
    if V is not empty 
    emit g 
    for every v in V { 
    find set V' of vertices not in g 
    for every v' in V' { 
     g' = g with new edge from v to v' 
     graph(g') 
    } 
    } 
} 
+1

Это, кажется, исключает все графики, которые включают в себя два ребра, идущие в одну и ту же вершину. – sprinter

+0

Я уставился на это некоторое время, прежде чем публиковать мысли о том же, но убедил себя иначе. Существует одна ошибка с начальным условием (требуется начальный край). – pmorken

2

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

void getAllEdgeSets(List<Edge> currentEdges, List<Edge> remainingEdges) { 
    if (remainingEdges.isEmpty()) { 
     processSet(currentEdges); 
    } else { 
     Edge edge = remainingEdges.remove(0); 
     getAllEdgeSets(currentEdges, remainingEdges); 
     currentEdges.add(edge); 
     getAllEdgeSets(currentEdges, remainingEdges); 
     currentEdges.remove(edge); 
    } 
} 

это называется с пустым списком, чтобы начать с:

getAllEdgeSets(Collections.EMPTY_LIST, edges); 

Вы также можете превратить это в источник для потока, так что вы можете обрабатывать, как вы идете (потенциально параллельно):

streamAllGraphs(5).filter(Graph::isAcyclic).forEach(...); 
+0

Спасибо. Я реализую нечто подобное. Да, цель состоит в том, чтобы получить все неориентированные графики с m ребрами для каждого m между 0 и n (n-1)/2. Для каждого m найдутся (n выбирают m) неориентированные графы. Ваш код выводит подмножество из них (проверял его на (0,1) (0,2) (1,2), который представляет все неориентированные ребра для n = 3). Еще раз спасибо. – Xline

+0

Это также должно быть тривиально, чтобы изменить его на направленные ребра. Класс Edge нуждается в исходной и целевой вершине, а затем метод генерации всех ребер генерирует в обоих направлениях. – sprinter

+0

Также обратите внимание, что это довольно неэффективно, если вы просто отфильтровываете циклические графики. Вы можете изменить его, чтобы отфильтровать оставшиеся значения для тех, которые не вызывают циклы перед рекурсированием. – sprinter

Смежные вопросы