11
votes

Logique pour placer stratégiquement des éléments dans un conteneur avec des connexions minimales qui se chevauchent

Ceci est plus d'une question algorithmique. J'ai une page qui utilise JavaScript affiche des éléments et des éléments relation avec un autre élément en dessinant une connexion arrow de la source à la cible (pensez jsplumb). Chaque élément peut avoir 0 connexions ou plus. Le défi que j'ai est de placer les divs / cercles de manière stratégique avec le conteneur de la manière la plus optimale.

  • Optimum: moins de connexions (flèches reliant deux cercles) chevauchent

    Exemple visuel: ci-dessous Image est une version non exchamisée de l'écran, après avoir placé les cercles au hasard dans le conteneur.

    Entrez la description de l'image ici

    avis dans l'image ci-dessus Le nombre de chevauchements de connexion (flèches) est inutilement élevé. Au-dessous de la photo est une solution optimisée avec des cercles placés dans une meilleure position, ce qui ne se chevauchent pas de connexion dans ce petit exemple:

    Entrez la description de l'image ici

    La taille du conteneur dans lequel les éléments sont placés est 1020x800. Lorsqu'il existe un grand nombre de cercles, il y aura toujours des chevauchements afin que l'idée soit de minimiser la quantité de chevauchement de la connexion. J'espère que l'exemple de la façon dont cela pourrait être fait car je trouve des articles de lecture d'algorithme légèrement décourageant: (.


15 commentaires

Dupliqué possible de Code de visualisation du graphique dans JavaScript?


@Davideisenstat je suis en désaccord - votre thread mentionné demande des moyens de grapher des nœuds de graphique sur une page Web, ma question est très différente dans celle qu'elle n'est pas limitée aux pages Web et qu'il s'agit d'une question de résolution de problèmes / algorithmes plutôt que de Utilisation de la bibliothèque X / Y pour représenter un graphique.


Avez-vous des liens avec les journaux que vous avez étudiés?


@arynaq Online Articles Non, mais c'est le livre que j'ai de mes journées de l'Université dans l'ingénierie logicielle ( amazon.com/algorithm-design-jon-kleinberg/dp/0321295358 ) Mais n'a pas réussi à trouver quelque chose qui m'aiderait.


Que diriez-vous de longueurs de bord minimes? "Optimal" pourrait-il également inclure des bords plus courts?


Related: Stackoverflow.com/Questtions/13318489/...


Connexes: Stackoverflow.com/Questions / 13447538 / ...


Connexes (certains aspects peut être NP): en.wikipedia.org/wiki/crossing_number_(Graph_Theory)


Je pense que le terme technique sera le suivant: "Minimisation du numéro de croisement" ... Il y a des tas d'articles savants à ce sujet sur l'érudit et ailleurs.


D3's Forcer le graphique dirigé aiderait probablement ici ici. Les choses non liées seront plus éloignées, de sorte que le graphique devrait vous démêler.


Dans votre exemple non optimisé , si je mettez B à droite, entre C et d , je pourrais dessiner le Connexion à partir de B à E comme un arc dans le sens anti-horaire s'étendant vers le haut et autour de C et la connexion de d à < Code> E comme un arc dans le sens anti-horaire s'étendant vers le bas et autour de a . Cela éviterait les chevauchements. Serait-ce une solution acceptable possible (une solution qui inclut la dessin des arcs autour des nœuds)?


Voir Stackoverflow.com/questions/2347748/planar-graph-layouts


@groovy oui c'est une solution acceptable.


@TechVenture Dans ce cas, je me suis juste pensé à un non-phase plus simple qui maintient les éléments de votre impérieux exemple en place: pour éviter les chevauchements, la flèche de d à à E pourrait aller dans le sens inverse des aiguilles d'une montre sous A , à condition que la flèche de B sur c irait dans le sens des aiguilles d'une montre arc sur e . Il y a au moins deux autres moyens qui garderaient les éléments en place. Problème intéressant!


@TechVenture en pensant plus à ce sujet, si vous permettez à la dessin des arcs autour des nœuds, la question (au moins pour votre exemple) peut devenir l'un des "confinement", c'est-à-dire quels arcs (connexions) contiennent des nœuds. Dans votre solution exemple, aucune des connexions "ne contient" nœuds.


3 Réponses :


2
votes

Il ressemble à une simple extraction de polygone fermée. Essayez ceci:

  1. oublier la direction des connexions Supprimer toutes les connexions redondantes (bidirectionnelles sont dupliquées)

  2. Trouver toutes les boucles fermées

    Le point de démarrage est toujours conteneur avec plus de 2 connexions (ou simplement avec 1) de sorte que la boucle à travers des conteneurs voisins non utilisés jusqu'à ce que reprenez le point de démarrage (définissez ce chemin comme utilisé) ou jusqu'à atteindre un point de terminaison (1 connexion seulement, également définie. Ce chemin utilisé) ou jusqu'à atteindre le carrefour (connexions> 2, définissez également ce trajet tel que utilisé).

  3. répéter jusqu'à ce qu'il n'y ait pas de ligne inutilisée entre les conteneurs restants.

    Après cela, vous avez votre graphique décomposé aux pièces non intersectées.

    Rejoignez-les maintenant ensemble afin qu'aucune connexion n'est intersectée. Les connexions partagées sont à l'intérieur et les connexions non partagées sont à l'extérieur. Boucle ouverte (avec des points d'extrémité) peut être n'importe où.

    J'espère que cela aide


3 commentaires

Bon, mais certains graphiques ne sont pas planifiés?


Le nombre de dimensions ne devrait pas avoir d'importance. Lorsque vous placez une boucle fermée à son voisin et que vous ne pouvez pas faire cela sans intersecter des objets déjà placés dans le plan XY, placez-le à la position libre suivante Tothe Plan XY (tournez autour du bord partagé par exemple)


Le problème avec cette approche est qu'il peut y avoir de nombreuses boucles fermées se croisant, puis il n'ya aucun moyen de les mettre en place sur un plan 2D sans intersections. En outre, le nombre de toutes les boucles fermées (cycles) peut augmenter de manière exponentielle avec le nombre de bords, de sorte qu'ils puissent tous être un coût prohibitif. Comment cet algorithme est censé mettre des cliques de mise en page?



8
votes

Approche 1

Une assez belle classe d'algorithmes pour la pose de graphiques sont des algorithmes à base de simulation. Dans ces algorithmes, vous modélisez votre graphique comme s'il s'agissait d'un objet physique avec des propriétés physiques.

Dans ce cas, imaginez que les nœuds du graphique sont des balles qui se repoussent, tandis que les bords sont des ressorts ou des caoutchoucs qui maintiennent le graphique ensemble. La force repoussante est plus forte plus les nœuds sont plus proches les uns des autres par exemple. carré inverse de leur distance et la force de tension de chaque ressort est proportionnelle à sa longueur. La force repoussante entraînera les nœuds d'obtenir autant que possible des autres nœuds et le graphique se débrouillera. Bien sûr, vous devrez expérimenter des coefficients un peu pour obtenir les meilleurs résultats (mais je vous garantis - c'est beaucoup de plaisir).

Les principaux avantages de cette approche sont les suivants:

  1. Facile à coder - Des boucles imbriquées en calculant la force entre chaque paire de nœuds et la mise à jour de la position de nœud
  2. fonctionne pour toutes sortes de graphiques de planar ou de nonplanar
  3. beaucoup de plaisir à expérimenter
  4. Si vous le faites interactif, par exemple. Autoriser l'utilisateur à déplacer des nœuds avec une souris - il attire les gens et tout le monde veut "jouer avec le graphique"

    Les inconvénients de cette approche sont les suivants:

    1. Il peut rester coincé dans un minimum d'énergie local (secouant ou aide manuellement)
    2. Ce n'est pas extrêmement rapide (mais peut faire une belle animation)

      une méthode similaire peut être utilisé pour la mise en page / des noeuds dénués.

      code d'échantillon xxx

      Vous pouvez voir comment ce code fonctionne ici . Actualisez la page pour obtenir différents graphiques. Bien sûr, parfois, il ne trouve pas le minimum global et il y a plus de bords croisés qu'il n'est possible, donc si les résultats ne vous satisfont pas, vous pouvez ajouter des secousses aléatoires.

      approche 2

      Ce problème est similaire au problème de routage dans la conception des PCB. Si vous n'êtes pas satisfait de la solution simple et facile fournie par APPROCHE 1, vous pouvez améliorer la solution en utilisant des méthodes d'autoroute. Par exemple. Vous pouvez mettre vos nœuds sur une grille puis utiliser un * algorithme * pour trouver les chemins les plus courts qui les connectent.

      1. Utilisez l'approche 1 pour trouver une solution initiale sous-optimale (facultatif).
      2. supprimer tous les bords. Placez les nœuds sur une grille (arrondir leurs coordonnées). La grille doit avoir suffisamment de résolution pour que les deux nœuds ne se chevauchent pas.
      3. Trier les bords de longueur approximative ascendante (utilisez une métrique Euclidean ou Manhattan).
      4. Pour chaque bord, utilisez un * algorithme pour trouver la voie la plus courte pour connecter les nœuds. En tant que fonction de coût, utilisez non seulement la distance entre le nœud source, mais aussi ajouter suffisamment de pénalité pour marcher sur les points de grille déjà pris par n'importe quel bord de bord précédemment.
      5. Marquez les points de grille sur le chemin trouvé à l'étape précédente comme "prise", de sorte que tous les bords suivants favoriseront les chemins ne pas marcher / intersecteront avec ce chemin.

        L'algorithme ci-dessus est une heuristique gourmande et il ne garantit malheureusement pas la solution optimale, car le résultat dépend de l'ordre de routage des bords. Vous pouvez améliorer encore la solution en retirant un bord aléatoire qui traverse un autre bord et le redirige.

        Étape 1. est facultatif pour rendre la disposition de graphique plus régulière et rendre la distance de connexion moyenne faible, mais il ne doit pas affecter le nombre d'intersections (si la grille a suffisamment de résolution). < / h1>


3 commentaires

Wow ne pensait pas à ceci (déjà fait ce genre de simulation de physique quelques années de retour et il était vraiment amusant) pour des graphiques planaires non complexes, il devrait fonctionner, mais pendant plus de 2D n'est aucune chance d'assurer aucune intersections entre les couches.


J'ai essayé cette approche, mais il est presque toujours coincé dans le Min / Max local. Il trouve une solution uniquement avec l'aide manuelle de glisser / secaking (même pour l'exemple ci-dessus qui est simple :() (essayé les connexions en tant que ressorts et nœuds comme une masse chargée avec la même polarité). Je pense qu'une combinaison avec mon approche serait meilleure (Pour définir différents paramètres de ressort pour les ressorts intérieurs et une meilleure position de démarrage).


J'apprécie vraiment votre exemple parce qu'il est propre et didactique. Comment calculeriez-vous la distance - et repousser soudainement et attirer des forces - pour des formes rectangulaires où un côté est beaucoup plus grand que l'autre?



0
votes

Je pense que l'algorithme basé sur la simulation serait le choix Bbest, cependant, étant donné que votre objectif est de minimiser les arcs qui se chevauchent et de ne pas optimiser la distribution des nœuds, vous devez appliquer une force repoussante entre les arcs (pas entre les nœuds) et utiliser le nœuds comme ressorts.

Itération:

  1. pour chaque arc dans le graphique calculer son point central (moyennant la moyenne du point de départ avec le point de fin)
  2. pour chaque couple d'arcs appliquent une répulsion entre leurs centres (les deux extrêmes de l'arc bougent en conséquence)
  3. Pour chaque nœud du graphique calculer sa nouvelle position en tant que moyenne des arcs connectés et mettez à jour le point final correspondant de l'arc

    Vous pouvez également ajouter une phase de contraction avec les nœuds attirés au milieu du graphique (moyenne des coordonnées de tous les nœuds).

    Arrêtez-vous quand un seuil de stabilité est atteint.


0 commentaires