Supposons que je suis un programmeur et que j'ai un problème NP-complet dont j'ai besoin pour le résoudre. Quelles méthodes sont disponibles pour traiter les problèmes des PNJ? Existe-t-il une enquête ou quelque chose de similaire sur ce sujet?
Supposons que je suis un programmeur et que j'ai un problème NP-complet dont j'ai besoin pour le résoudre. Quelles méthodes sont disponibles pour traiter les problèmes des PNJ? Existe-t-il une enquête ou quelque chose de similaire sur ce sujet?
Réponses:
Il existe un certain nombre de stratégies bien étudiées; Ce qui convient le mieux à votre application dépend des circonstances.
Améliorer le pire temps d'exécution
En utilisant des informations spécifiques à un problème, vous pouvez souvent améliorer l'algorithme naïf. Par exemple, il existe desalgorithmes pour la couverture de sommet avec [1]; C'est une énorme amélioration par rapport au naïf et pourrait rendre les tailles d'instance pertinentes pour vous.
Améliorez le temps d'exécution attendu
À l'aide de méthodes heuristiques, vous pouvez souvent concevoir des algorithmes rapides sur de nombreuses instances. Si ceux-ci incluent le plus que vous rencontrez dans la pratique, vous êtes en or. Des exemples sont SAT pour lesquels des solveurs assez impliqués existent, et l'algorithme Simplex (qui résout un problème polynomial, mais quand même). Une technique de base souvent utile est la ramification et la liaison .
Limitez le problème
Si vous pouvez faire plus de suppositions sur vos entrées, le problème peut devenir facile.
Affaiblir le résultat
Cela signifie que vous tolérez des résultats erronés ou incomplets. Il y a deux saveurs principales:
Reportez-vous à la section Algorithmics for Hard Problems de Hromkovič pour un traitement approfondi.
D'autres réponses ont abordé cette question d'un point de vue plus théorique. Voici une approche plus pratique.
Pour les problèmes de décision NP-complets "typiques" ( "existe-t-il un objet qui satisfasse à toutes ces contraintes?" ), Voici ce que j'essaierais toujours en premier:
Ecrivez un programme simple qui code votre instance problématique en tant qu’instance SAT .
Ensuite, prenez un bon solveur SAT , lancez-le (en utilisant l'ordinateur multi-cœur le plus rapide que vous possédez) et voyez ce qui se passe.
Essayez d’abord avec les plus petites instances pour avoir une idée du temps que cela pourrait prendre.
Étonnamment souvent, cette approche est bien meilleure que d'essayer de mettre en œuvre votre propre solutionneur spécifiquement pour votre problème actuel:
Les solveurs SAT sont très intelligents et bien optimisés. Ils surperforment facilement votre propre implémentation de la recherche arrière (peu importe le temps que vous perdez à optimiser votre code). Ils surpassent également facilement de nombreuses alternatives originales telles que les solveurs de programmation linéaire entier.
Cela nécessite très peu de programmation. L'étape 1 est relativement simple et n'est pas critique en termes de performances; vous pouvez utiliser des langages de script tels que Python. Quelqu'un d'autre s'est déjà chargé de mettre en œuvre tout ce dont vous avez besoin pour l'étape 2.
Pour les problèmes d’ optimisation NP-hard typiques ( "trouver la plus petite chose qui réponde à toutes ces contraintes" ), cette approche peut ne pas fonctionner.
Si vous pouvez facilement en faire un problème de décision ( "existe-t-il un objet de taille 4 qui réponde à toutes ces contraintes?" , "Et la taille 3?" ), Bien, suivez la même approche que ci-dessus pour les problèmes de décision.
Sinon, vous voudrez peut-être recourir à un résolveur heuristique qui tente de trouver une petite solution (pas nécessairement la plus petite solution). Par exemple:
Encodez votre problème en tant qu'instance MAX-SAT (pondérée) .
Utilisez les solveurs heuristiques du package UBCSAT . Les solveurs heuristiques parallélisent trivialement; essayez de trouver un cluster avec des centaines d’ordinateurs. Vous pouvez exécuter les solveurs aussi longtemps que vous le souhaitez, puis adopter la meilleure solution que vous avez trouvée jusqu'à présent.
Une façon d’attaquer l’intractabilité consiste à réfléchir au problème dans le contexte de complexité paramétrée.
Voici quelques exemples dans différentes classes de la hiérarchie W:
Il existe un autre niveau de complexité pour classer les problèmes de NP de manière plus précise. Si vous en voulez davantage, vous pouvez vous pencher sur la complexité des circuits paramétrés et la hiérarchie W de Downey et al (1998).
Et si vous voulez encore plus, c'est bien de lire la théorie de la complexité paramétrée de Flum and Grohe .
Et enfin:
On sait que si le problème a FPTAS ( schéma d'approximation entièrement polynomiale ), il l'est également (FPT) (ce qui est évident) La relation entre PTAS et la hiérarchie W n’est pas très étroite (du moins je ne le sais pas pour le moment).
Dans certains cas, nous pouvons également fixer différents paramètres, par exemple: la longueur du plus long chemin du graphe est liée et la taille de la solution est délimitée (par exemple, dans le jeu de sommets de retour), ...
Certaines personnes peuvent penser que la complexité paramétrée est inutile dans la pratique. Mais c'est faux. De nombreux algorithmes paramétrés sont découverts dans des applications du monde réel. Lorsque vous pouvez corriger certains paramètres, voici un exemple:
L'un des algorithmes heuristiques les plus rapides et les plus précis pour TSP est le suivant: Fusion de tours et décomposition de branches , qui utilise le paramétrage du problème (pas directement, mais la décomposition de branches et l'approche de programmation dynamique utilisée reposent sur de bonnes hypothèses).
L'exhaustivité des NP concerne la pire intolérance. En fonction du problème sur lequel vous travaillez, de nombreuses classes d'instances peuvent être résolues dans un délai raisonnable (bien que vous ayez peut-être besoin d'un algorithme plus spécialisé pour obtenir les bonnes durées d'exécution).
Envisagez de vérifier s'il existe une solution efficace de votre problème à un problème avec de bons résolveurs disponibles, tels que la satisfaction booléenne ou la programmation linéaire en nombres entiers.
Bien que brièvement évoqué dans certaines des réponses, je tiens à souligner que, dans la pratique, les problèmes NP-complets sont résolus (ou approximés) à tout moment. La principale raison pour laquelle vous pouvez résoudre des problèmes NP-complets dans la pratique est:
Les instances rencontrées dans la pratique ne constituent pas le "pire des cas".
Une autre raison de la différence est:
Il est difficile d’analyser formellement les algorithmes heuristiques.
En pratique, vous utilisez des algorithmes heuristiques pour résoudre vos problèmes NP-complets et vous espérez que tout ira bien. Les résultats sont souvent stupéfiants.
Un autre problème abordé dans d'autres réponses est le suivant:
Parfois, les algorithmes exponentiels sont assez rapides.
Cela dépend bien sûr du problème. Lorsque le Big Data est impliqué, nous avons la maxime opposée:
Parfois, les seuls algorithmes possibles sont quasi linéaires.
Je crains que la foule ici ne soit plutôt encline à la théorie. Vous obtiendrez peut-être de meilleures réponses sur le site stackexchange principal.