Dans l' introduction aux algorithmes de Cormen et al. , La section 15.3 Éléments de programmation dynamique explique la mémorisation comme suit:
Un algorithme récursif mémorisé conserve une entrée dans une table pour la solution de chaque sous-problème. Chaque entrée de table contient initialement une valeur spéciale pour indiquer que l'entrée doit encore être remplie. Lorsque le sous-problème est rencontré pour la première fois au fur et à mesure que l'algorithme récursif se déroule, sa solution est calculée puis stockée dans la table. Chaque fois que nous rencontrons ce sous-problème, nous recherchons simplement la valeur stockée dans la table et la renvoyons.
Et il ajoute, en note de bas de page:
Cette approche suppose que nous connaissons l'ensemble de tous les paramètres de sous-problème possibles et que nous avons établi la relation entre les positions de table et les sous-problèmes. Une autre approche, plus générale, consiste à mémoriser en utilisant le hachage avec les paramètres de sous-problème comme clés.
Existe-t-il des problèmes DP bien connus qui nécessitent (ou facilitent) le stockage des valeurs mémorisées dans un dictionnaire plutôt que dans un tableau (multidimensionnel)?
Contexte: si cela est utile, la raison de cette question est que j'essaie de motiver la notion d'arbres de recherche binaires (auto-équilibrés) pour les personnes qui viennent de voir la programmation dynamique.
Réponses:
Il y a probablement de meilleurs exemples, mais en voici un, au-dessus de ma tête:
Disons que vous voulez vérifier si la distance d'édition entre deux chaînes est , et si c'est le cas, calculer la distance d'édition. Vous pouvez utiliser l'algorithme de programmation dynamique standard pour calculer la distance d'édition, mais "élaguer" le calcul (arrêter la récursivité) à tout endroit où la distance d'édition est connue pour être . Cela signifie que vous n'aurez probablement pas besoin de remplir tout le tableau; vous n'aurez qu'à remplir certaines des entrées. Ainsi, l'utilisation d'un dictionnaire peut améliorer les performances.S, T ≤ d > d
la source
Je voudrais donner 2 exemples.
0-1 Problème de sac à dos
En cas de problème de sac à dos 0-1 (où W est une capacité du sac à dos et N est une quantité d'articles), il est parfois préférable d'utiliser la programmation dynamique descendante avec mémorisation, au lieu de l'énumération ascendante systématique de la totalité du tableau 2D de taille WxN (en particulier dans le cas où la capacité du sac à dos W est grande, mais la cardinalité de l'ensemble des combinaisons autorisées de poids d'articles est beaucoup plus petite que W ).
Dans ce cas, pour des raisons d'économie de mémoire, on peut choisir d'utiliser le dictionnaire pour la mémorisation au lieu du tableau 2D.
Algorithme d'analyse Earley
L'algorithme d'analyse Earley peut être utilisé pour l'analyse des instructions, qui appartiennent à une grammaire sans contexte. Contrairement à l'algorithme CYK (qui est basé sur l'approche DP ascendante et utilise une table 2D pour la mémorisation) - l'analyseur Earley utilise l'approche descendante en combinaison avec le tableau d'analyse pour la mémorisation.
Le tableau d'analyse contient les productions grammaticales partiellement analysées (par exemple: étant donné la production X → AB , et après un appariement réussi de la partie A de cette production, nous stockons la production partiellement appariée à l'intérieur du tableau d'analyse: X → A • B , où le point pointe à la partie déjà appariée).
Le nombre de colonnes à l'intérieur du graphique d'analyse égal au nombre de jetons. Cependant, dans le cas général, il peut être très difficile d'estimer la quantité de productions grammaticales partiellement analysées par colonne (cela dépend de la grammaire et de la séquence particulière de jetons).
Par conséquent, il est plus pratique d'implémenter le graphique d'analyse basé sur la structure de données du dictionnaire.
Dans le domaine du traitement du langage naturel, le pareser Earley est généralement un choix plus pratique, car il ne nécessite pas la forme normale de Chomsky pour la grammaire (et CYK a une telle exigence).
la source
D'après mon expérience de la programmation concurrentielle, l'utilisation d'une table de hachage (Python
dict
ou similaire) est souvent plus pratique que l'utilisation d'un tableau, car tout type de données lavables peut être utilisé comme clé, comme des chaînes, des ensembles (frozenset
en Python) ou des tuples comme(string, int)
etc. Si vous utilisez un tableau, vous devez traduire manuellement toutes les clés en nombres entiers (à partir de 0), ce qui nécessite un travail supplémentaire et, comme le note votre source, peut ne pas être possible si vous ne connaissez pas l'espace des clés à l'avance. Les dictionnaires sont donc plutôt plus généraux que les tableaux.Bien sûr, si vous pouvez vous en sortir en utilisant des tableaux, c'est probablement plus rapide car cela évite de calculer de manière répétée les hachages (d'un autre côté, il faut d'abord initialiser tout le tableau, ce qui prend du temps et de la mémoire), mais cela peut prendre plus de temps pour écrire le code car vous devez faire le travail supplémentaire de traduction de toutes les clés en nombres entiers.
la source