53 votes

Segments de ligne ne se recoupant pas tout en minimisant la longueur cumulée

J'aimerais trouver un meilleur algorithme pour résoudre le problème suivant :

Il y a N points de départ (violet) et N points cibles (en vert) en 2D. Je veux un algorithme qui relie les points de départ aux points cibles par un segment de ligne (marron) sans qu'aucun de ces segments ne se croise (rouge) et en minimisant la longueur cumulée de tous les segments.

Mon premier effort en C++ a consisté à permuter tous les états possibles, à trouver des états sans intersection et, parmi ceux-ci, l'état dont la longueur totale du segment est la plus faible O(n !) . Mais je pense qu'il doit y avoir une meilleure façon de procéder.

enter image description here

Une idée ? Ou de bons mots-clés pour la recherche ?

0 votes

Peut-être une sorte de tri topologique ?

0 votes

Je ne connais pas non plus la réponse, mais je créerais n'importe quelle solution (en ignorant les conflits) et je résoudrais ensuite les conflits individuellement : lorsque deux lignes sont en conflit, il semble que le fait d'intervertir une paire de points d'extrémité résolve le conflit. Je ne sais pas comment garantir la progression, cependant.

1 votes

@DietmarKühl : Le changement de point de terminaison pourrait entraîner l'apparition d'un conflit différent.

38voto

qq3 Points 396

T M .

0 votes

@

0 votes

@dmckee : qq3 a dit que la règle de non-intersection était redondant sous la contrainte de longueur totale minimale, et non "en conflit" avec elle (mathématiquement, il s'agit de très différentes). Et pour B (ce qui est le cas ici), les améliorations localement séparables sont aussi toujours des améliorations globalement valides, de sorte que la règle de croisement des longueurs locales s'applique aussi globalement. (Je ne suis pas sûr que cela s'applique aux cas non bipartites, les cas bipartites étant beaucoup plus simples).

0 votes

@RBarryYoung> Ah....e commentaire (que je vais maintenant supprimer) n'a plus de sens car le commentaire auquel je répondais a été supprimé. Nous sommes d'accord.

3voto

Saeed Amiri Points 16317

Vous pouvez sélectionner une connexion aléatoire, puis à chaque fois supprimer une croix en changeant les connexions de ses points d'extrémité. Cette opération réduit la longueur totale (par inégalité des triangles). Comme le nombre de façons dont les lignes se croisent est fini, nous arrivons à une solution sans croisement en un nombre fini d'étapes. En pratique, cette solution devrait converger rapidement.

0 votes

@MasoudM. Je suis sûr à 100% que la commutation des croix va finalement s'arrêter (la longueur totale diminue). Si vous vous souciez du temps (combien de fois vous devez le faire), parce que votre programme fonctionne sur des machines finies (PC), elles n'ont pas quelque chose comme epsilon (qui pourrait être très petit), leur précision est prédéfinie (par exemple 30 bits), donc il peut être terminé rapidement, et vous pouvez également ajouter quelques heuristiques à chaque étape, pour avoir une meilleure sélection dans les changements. Je vous suggère d'implémenter ceci (vous avez besoin de certaines bases dans tous les autres algorithmes comme la recherche d'intersection et le changement de certaines d'entre elles sont nécessaires dans tous les algorithmes).

1 votes

La longueur totale diminue mais elle est finie car elle sera au moins égale à zéro.

0 votes

@MasoudM. Une heuristique utile consiste à trouver tous les conflits à chaque étape et à les résoudre, puis à rechercher à nouveau les conflits. Si vous lisez les articles suggérés par qq3, vous obtiendrez bien sûr une meilleure réponse que celle-ci.

1voto

Krumelur Points 8935

On dirait que vous pourriez utiliser un Type BSP algorithme.

1voto

M M. Points 29201

Suite à la réponse de qq3 qui dit la contrainte d'intersection est redondante, il ne reste plus qu'une étape à franchir. Assigner des points de départ à des points d'arrivée tout en minimisant la longueur totale. Heureusement, il existe un algorithme en temps polynomial pour cela :

Algorithme hongrois est une optimisation combinatoire qui résout le problème d'affectation en temps polynomial.

Il réduit le temps de commande de O(n !) a O(n 3 ) .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X