Qu'est-ce que la programmation dynamique ?
En quoi est-ce différent de la récursivité, de la mémorisation, etc.?
J'ai lu l' article wikipedia à ce sujet, mais je ne le comprends toujours pas vraiment.
Qu'est-ce que la programmation dynamique ?
En quoi est-ce différent de la récursivité, de la mémorisation, etc.?
J'ai lu l' article wikipedia à ce sujet, mais je ne le comprends toujours pas vraiment.
Réponses:
La programmation dynamique consiste à utiliser les connaissances passées pour faciliter la résolution d'un problème futur.
Un bon exemple est la résolution de la séquence de Fibonacci pour n = 1 000 002.
Ce sera un processus très long, mais que se passe-t-il si je vous donne les résultats pour n = 1 000 000 et n = 1 000 001? Soudain, le problème est devenu plus gérable.
La programmation dynamique est beaucoup utilisée dans les problèmes de chaîne, tels que le problème d'édition de chaîne. Vous résolvez un sous-ensemble du problème, puis utilisez ces informations pour résoudre le problème d'origine le plus difficile.
Avec la programmation dynamique, vous stockez généralement vos résultats dans une sorte de tableau. Lorsque vous avez besoin de la réponse à un problème, vous référencez le tableau et voyez si vous savez déjà de quoi il s'agit. Sinon, vous utilisez les données de votre tableau pour vous donner un tremplin vers la réponse.
Le livre Cormen Algorithms contient un excellent chapitre sur la programmation dynamique. ET c'est gratuit sur Google Livres! Découvrez-le ici.
la source
La programmation dynamique est une technique utilisée pour éviter de calculer plusieurs fois le même sous-problème dans un algorithme récursif.
Prenons l'exemple simple des nombres de Fibonacci: trouver le n ème nombre de Fibonacci défini par
F n = F n-1 + F n-2 et F 0 = 0, F 1 = 1
Récursivité
La façon évidente de le faire est récursive:
Programmation dynamique
La récursivité fait beaucoup de calculs inutiles car un nombre de Fibonacci donné sera calculé plusieurs fois. Un moyen simple d'améliorer cela est de mettre en cache les résultats:
Une meilleure façon de le faire est de se débarrasser de la récursivité en évaluant les résultats dans le bon ordre:
Nous pouvons même utiliser un espace constant et ne stocker que les résultats partiels nécessaires en cours de route:
Comment appliquer la programmation dynamique?
La programmation dynamique fonctionne généralement pour les problèmes qui ont un ordre inhérent de gauche à droite tels que les chaînes, les arbres ou les séquences entières. Si l'algorithme récursif naïf ne calcule pas le même sous-problème plusieurs fois, la programmation dynamique n'aidera pas.
J'ai fait une collection de problèmes pour aider à comprendre la logique: https://github.com/tristanguigue/dynamic-programing
la source
if n in cache
comme avec l'exemple de haut en bas ou est-ce que je manque quelque chose.La mémorisation est le moment où vous stockez les résultats précédents d'un appel de fonction (une fonction réelle renvoie toujours la même chose, étant donné les mêmes entrées). Cela ne fait aucune différence pour la complexité algorithmique avant le stockage des résultats.
La récursivité est la méthode d'une fonction qui s'appelle elle-même, généralement avec un ensemble de données plus petit. Comme la plupart des fonctions récursives peuvent être converties en fonctions itératives similaires, cela ne fait pas non plus de différence pour la complexité algorithmique.
La programmation dynamique est le processus de résolution de sous-problèmes plus faciles à résoudre et de construction de la réponse à partir de cela. La plupart des algorithmes DP seront dans les temps d'exécution entre un algorithme gourmand (s'il en existe un) et un algorithme exponentiel (énumérer toutes les possibilités et trouver la meilleure).
la source
C'est une optimisation de votre algorithme qui réduit le temps d'exécution.
Alors qu'un algorithme gourmand est généralement appelé naïf , car il peut s'exécuter plusieurs fois sur le même ensemble de données, la programmation dynamique évite cet écueil grâce à une compréhension plus approfondie des résultats partiels qui doivent être stockés pour aider à construire la solution finale.
Un exemple simple est de parcourir un arbre ou un graphique uniquement à travers les nœuds qui contribueraient à la solution, ou de mettre dans un tableau les solutions que vous avez trouvées jusqu'à présent afin d'éviter de parcourir les mêmes nœuds encore et encore.
Voici un exemple d'un problème adapté à la programmation dynamique, tiré du juge en ligne d'UVA: Edit Steps Ladder.
Je vais faire un bref exposé de la partie importante de l'analyse de ce problème, tirée du livre Programming Challenges, je vous suggère de le vérifier.
Ici, une analyse très particulière de ce qu'il faut pour obtenir les résultats partiels les plus optimaux est ce qui fait de la solution une solution «dynamique».
Voici une solution alternative et complète au même problème. Il est également "dynamique" même si son exécution est différente. Je vous suggère de vérifier l'efficacité de la solution en la soumettant au juge en ligne d'UVA. Je trouve étonnant de voir comment un problème aussi lourd a été abordé si efficacement.
la source
Les bits clés de la programmation dynamique sont les "sous-problèmes qui se chevauchent" et la "sous-structure optimale". Ces propriétés d'un problème signifient qu'une solution optimale est composée des solutions optimales à ses sous-problèmes. Par exemple, les problèmes de chemin le plus court présentent une sous-structure optimale. Le chemin le plus court de A à C est le chemin le plus court de A à un nœud B suivi du chemin le plus court de ce nœud B à C.
Plus en détail, pour résoudre un problème de chemin le plus court, vous devrez:
Parce que nous travaillons de bas en haut, nous avons déjà des solutions aux sous-problèmes quand vient le temps de les utiliser, en les mémorisant.
N'oubliez pas que les problèmes de programmation dynamique doivent avoir à la fois des sous-problèmes qui se chevauchent et une sous-structure optimale. La génération de la séquence de Fibonacci n'est pas un problème de programmation dynamique; il utilise la mémorisation parce qu'il a des sous-problèmes qui se chevauchent, mais il n'a pas de sous-structure optimale (car il n'y a pas de problème d'optimisation impliqué).
la source
Programmation dynamique
Définition
La programmation dynamique (DP) est une technique générale de conception d'algorithmes pour résoudre des problèmes avec des sous-problèmes qui se chevauchent. Cette technique a été inventée par le mathématicien américain "Richard Bellman" dans les années 1950.
Idée clé
L'idée clé est de sauvegarder les réponses des sous-problèmes plus petits qui se chevauchent pour éviter le recalcul.
Propriétés de programmation dynamique
la source
Je suis également très nouveau dans la programmation dynamique (un algorithme puissant pour un type de problème particulier)
En termes plus simples, il suffit de penser la programmation dynamique comme une approche récursive en utilisant les connaissances précédentes
Connaissances antérieures sont ce qui importe le plus ici, gardez une trace de la solution des sous-problèmes que vous avez déjà.
Considérez ceci, l'exemple le plus basique pour dp de Wikipedia
Trouver la séquence de fibonacci
Permet de décomposer l'appel de fonction avec disons n = 5
En particulier, fib (2) a été calculé trois fois à partir de zéro. Dans de plus grands exemples, beaucoup plus de valeurs de fib, ou sous-problèmes, sont recalculées, conduisant à un algorithme de temps exponentiel.
Maintenant, essayons en stockant la valeur que nous avons déjà trouvée dans une structure de données, par exemple une carte
Ici, nous sauvegardons la solution des sous-problèmes dans la carte, si nous ne l'avons pas déjà. Cette technique de sauvegarde des valeurs que nous avions déjà calculées est appelée mémorisation.
Enfin, pour un problème, essayez d'abord de trouver les états (sous-problèmes possibles et essayez de penser à la meilleure approche de récursivité afin que vous puissiez utiliser la solution du sous-problème précédent dans d'autres).
la source
La programmation dynamique est une technique pour résoudre des problèmes avec des sous-problèmes qui se chevauchent. Un algorithme de programmation dynamique résout chaque sous-problème une seule fois, puis enregistre sa réponse dans une table (tableau). Éviter le travail de recalcul de la réponse à chaque fois que le sous-problème est rencontré. L'idée sous-jacente de la programmation dynamique est la suivante: éviter de calculer deux fois la même chose, généralement en conservant un tableau des résultats connus des sous-problèmes.
Les sept étapes du développement d'un algorithme de programmation dynamique sont les suivantes:
la source
6. Convert the memoized recursive algorithm into iterative algorithm
une étape obligatoire? Cela signifierait que sa forme finale est non récursive?en bref la différence entre la mémorisation récursive et la programmation dynamique
La programmation dynamique comme son nom l'indique utilise la valeur calculée précédente pour construire dynamiquement la prochaine nouvelle solution
Où appliquer la programmation dynamique: si votre solution est basée sur une sous-structure optimale et un sous-problème qui se chevauchent, alors dans ce cas, l'utilisation de la valeur calculée plus tôt sera utile pour que vous n'ayez pas à la recalculer. C'est une approche ascendante. Supposons que vous devez calculer fib (n) dans ce cas, tout ce que vous devez faire est d'ajouter la valeur calculée précédente de fib (n-1) et fib (n-2)
Récursion: Fondamentalement, vous subdivisez votre problème en une partie plus petite pour le résoudre facilement, mais gardez-le à l'esprit, cela n'évite pas le recalcul si nous avons la même valeur calculée précédemment dans un autre appel de récursivité.
Mémorisation: Le stockage de l'ancienne valeur de récursion calculée dans le tableau est connu sous le nom de mémorisation, ce qui évitera le recalcul s'il a déjà été calculé par un appel précédent, de sorte que toute valeur sera calculée une fois. Donc, avant de calculer, nous vérifions si cette valeur a déjà été calculée ou non si elle est déjà calculée, puis nous retournons la même chose de la table au lieu de recalculer. C'est aussi une approche descendante
la source
Voici un exemple simple de code python
Recursive
,Top-down
,Bottom-up
approche pour la série de Fibonacci:Récursif: O (2 n )
De haut en bas: O (n) Efficace pour une entrée plus importante
De bas en haut: O (n) pour la simplicité et les petites tailles d'entrée
la source