La génération aléatoire DAG
Je suis la résolution d'un problème sur le graphe dirigé acyclique.
Mais je vais avoir des ennuis pour tester mon code sur certains dirigé acyclique graphiques. Le test des graphiques doit être grande, et (évidemment) acycliques.
J'ai essayé beaucoup de choses à écrire du code pour générer les graphes orientés acycliques. Mais j'ai échoué à chaque fois.
Est-il une méthode pour générer des graphes orientés acycliques je pourrais utiliser?
- Comment pouvez-vous utiliser le C et le C++, mais de ne pas montrer tout le code?
- Je voudrais prendre quelques grands opensource netlist et rompre les boucles (le cas échéant) à l'aide d'un simple DFS à base de détecteur de boucle.
- "Je suis la souffrance", j'espère que ça ne fait pas de mal. Désolé, j'ai dû faire plaisir, mais votre niveau d'anglais est vraiment ok. Voir la fonction
directed_acyclic_graph
ici: condor.depaul.edu/rjohnson/source/graph_ge.c
Vous devez vous connecter pour publier un commentaire.
J'ai concocté un programme C qui fait cela. La clé est de "rang" les nœuds, et seulement tirer des bords à partir d'un rang inférieur, les nœuds de rang plus élevé chers.
Le programme que j'ai écrit imprime dans la DOT de la langue.
Voici le code lui-même, avec les commentaires expliquant ce que cela signifie:
Et voici le graphique généré à partir d'un test:
dot
programme fourni avec le GraphWiz le paquet.La réponse à https://mathematica.stackexchange.com/questions/608/how-to-generate-random-directed-acyclic-graphs s'applique: si vous avez une matrice de contiguïté de la représentation de la bords de votre graphe, si la matrice est triangulaire inférieure, c'est un groupe de nécessité.
Une approche similaire serait de prendre un arbitraire de la commande de vos nœuds, et d'examiner ensuite les bords de nœud x à y uniquement lorsque x < y. Cette contrainte devrait également obtenir votre DAGness par construction. Mémoire de comparaison, ce serait une façon arbitraire pour commander votre nœuds si vous êtes en utilisant des structures pour représenter les nœuds.
Fondamentalement, le pseudocode serait quelque chose comme:
où N est le nombre de nœuds dans votre graphique.
Le pseudocode suggère que le nombre potentiel de DAGs, étant donné N nœuds, est
puisqu'il y a
paires commandées ("N choisir 2"), et l'on peut choisir soit de prendre la tête entre eux ou pas.
maybePutAnEdgeBetween
procédure devrait faciliter.Vous pouvez générer de façon aléatoire un graphe orienté, et de procéder à une profondeur d'abord de recherche pour les cycles. Lorsque vous trouvez un cycle, de le briser par la suppression d'une arête.
Je pense que c'est le pire des cas O(VE). Chaque DFS prend O(V), et chacun d'eux supprime au moins une arête (donc max E)
Si vous générez le graphique dirigé par uniformément aléatoire de la sélection de tous les V^2 bords, et vous DFS dans un ordre aléatoire et supprimer un hasard de bord, ce serait vous donner une distribution uniforme (ou au moins presque) sur tous les possibles dags.
Donc, pour essayer de mettre tous ces des réponses raisonnables ensemble:
(Dans la suite, j'ai utilisé V pour le nombre de sommets dans le graphique généré, et E pour le nombre d'arêtes, et nous supposons que E ≤ V(V-1)/2.)
Personnellement, je pense que le plus utile de la réponse est dans un commentaire, par Flavius, qui indique le code à http://condor.depaul.edu/rjohnson/source/graph_ge.c. Ce code est très simple, et il est idéalement décrite par un commentaire, que je reproduis:
En fait, ce que fait le code est de générer de la demande de nombre d'arêtes de façon répétée en procédant de la manière suivante:
Le problème avec cette solution est que comme E est ferme pour le nombre maximum d'arêtes V(V-1)/2, alors l'algorithme devient plus lent et plus lent, car il a à rejeter de plus en plus et les bords. Une meilleure solution serait de faire un vecteur de V(V-1)/2 arêtes; de façon aléatoire shuffle, et sélectionnez le premier (demandé bords) les bords de la mélangées liste.
La réservoir algorithme d'échantillonnage nous permet de faire cela dans l'espace de O(E), puisque nous pouvons en déduire les points de terminaison de la kème de bord à partir de la valeur de k. Par conséquent, nous n'ont pas réellement de créer le vecteur source. Cependant, il faut O(V2) temps.
Sinon, on peut faire un De Fisher-Yates shuffle (ou Knuth shuffle, si vous préférez), en s'arrêtant après E itérations. Dans la version de l'EXERCICE shuffle présenté dans Wikipedia, cela permettra de produire de la fuite des entrées, mais l'algorithme fonctionne tout aussi bien à l'envers:
Cela nécessite seulement O(E) temps, mais elle nécessite O(N2) de l'espace. En fait, ce qui peut être amélioré à O(E) l'espace avec quelques astuces, mais une SORTE de fragment de code est trop petit pour contenir le résultat, je vais donc donner une plus simple en O(E) l'espace et O(E log E) de temps. Je suppose qu'il y a une classe de DAG avec au moins:
Maintenant, va ici:
Une approche très simple est:
D'attribuer au hasard des bords par itération sur les indices d'une baisse de la diagonale de la matrice (comme l'a suggéré un lien ci-dessus: https://mathematica.stackexchange.com/questions/608/how-to-generate-random-directed-acyclic-graphs)
Cela vous donnera un DAG avec éventuellement plus d'un composant. Vous pouvez utiliser un Disjoints-définir la structure de données pour vous donner les éléments qui peuvent ensuite être fusionnées en créant des bords entre les composants.
Disjoints-ensembles sont décrites ici: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
Créer un graphique avec
n
nœuds et une arête entre chaque paire de nœudsn1
etn2
sin1 != n2
etn2 % n1 == 0
.Récemment, j'ai essayé de re-mise en œuvre de la accepté de répondre et trouve que c'est indeterministic. Si vous n'imposez pas la min_per_rank paramètre, vous pourriez vous retrouver avec un graphique avec 0 nœuds.
Pour éviter cela, j'ai emballé pour les boucles dans une fonction, puis vérifié pour s'assurer qu'à l'issue de chaque rang, que
min_per_rank
a été satisfait. Voici le code JavaScript de la mise en œuvre:https://github.com/karissa/random-dag
Et de pseudo-code C qui remplacerait l'on a accepté la réponse de la boucle principale.