Avant de lire L'Art de la programmation informatique (TAOCP) , je n'ai pas approfondi ces questions. J'utiliserais un pseudo-code pour décrire des algorithmes, les comprendre et estimer le temps d'exécution uniquement sur les ordres de croissance. Le TAOCP change complètement d'avis.
TAOCP utilise un anglais mélangé avec des étapes et goto pour décrire l'algorithme, et utilise des organigrammes pour visualiser l'algorithme plus facilement. Cela semble de bas niveau, mais je trouve qu'il y a certains avantages, en particulier avec l'organigramme, que j'ai beaucoup ignoré. Nous pouvons étiqueter chacune des flèches avec une assertion sur l'état actuel des choses au moment où le calcul traverse cette flèche, et faire une preuve inductive pour l'algorithme. L'auteur dit:
Selon l'auteur, nous comprenons vraiment pourquoi un algorithme n'est valable que lorsque nous atteignons le point où nos esprits ont implicitement rempli toutes les affirmations, comme cela a été fait dans la Fig.4.
Je n'ai pas connu de telles choses. Un autre avantage est que nous pouvons compter le nombre de fois que chaque étape est exécutée. Il est facile de vérifier avec la première loi de Kirchhoff. Je n'ai pas analysé exactement le temps de fonctionnement, donc certains pourraient avoir été omis lors de l'estimation du temps de fonctionnement.
L'analyse des ordres de croissance est parfois inutile. Par exemple, nous ne pouvons pas distinguer le tri rapide du tri actif car ils sont tous , où est le nombre attendu de variable aléatoire , nous devons donc analyser la constante, disons, et , nous pouvons donc mieux comparer et . Et aussi, parfois, nous devons comparer d'autres quantités, telles que les variances. Seule une analyse grossière des ordres de croissance du temps de course ne suffit pas. Comme TAOCP traduit les algorithmes en langage assembleur et calcule le temps d'exécution, c'est trop difficile pour moi, donc je veux connaître quelques techniques pour analyser le temps d'exécution un peu plus approximativement, ce qui est également utile, pour les langages de plus haut niveau tels que C, C ++ ou pseudo-codes.
Et je veux savoir quel style de description est principalement utilisé dans les travaux de recherche et comment traiter ces problèmes.
Réponses:
Il existe une grande variété d'approches possibles. Ce qui convient le mieux dépend de
Si l'algorithme est largement connu et que vous utilisez comme sous-programme, vous restez souvent à un niveau supérieur. Si l'algorithme est l'objet principal étudié, vous voudrez probablement être plus détaillé. La même chose peut être dite pour les analyses: si vous avez besoin d'une limite d'exécution supérieure approximative, vous procédez différemment de lorsque vous voulez un décompte précis des instructions.
Je vais vous donner trois exemples pour l'algorithme bien connu Mergesort qui, espérons-le, illustrent cela.
Haut niveau
L'algorithme Mergesort prend une liste, la divise en deux parties (à peu près) également longues, revient sur ces listes partielles et fusionne les résultats (triés) afin que le résultat final soit trié. Sur des listes singleton ou vides, il renvoie l'entrée.
Cet algorithme est évidemment un algorithme de tri correct. Le fractionnement de la liste et sa fusion peuvent chacun être mis en œuvre dans le temps , ce qui nous donne une récurrence pour le pire cas d'exécution T ( n ) = 2 T ( nΘ(n) . Par le théorème maître, cela équivaut àT(n)∈Θ(nlogn).T(n)=2T(n2)+Θ(n) T(n)∈Θ(nlogn)
Niveau moyen
L'algorithme Mergesort est donné par le pseudo-code suivant:
Nous prouvons l'exactitude par induction. Pour les listes de longueur zéro ou un, l'algorithme est trivialement correct. Comme hypothèse d'induction, supposons qu'iln n>1 L n+1 L L
mergesort
fonctionne correctement sur des listes de longueur au plus pour certains n naturels arbitraires mais fixes n > 1 . Soit maintenant L une liste de longueur n + 1 . Par hypothèse d'induction, et maintenez (sans diminution) les versions triées du premier resp. seconde moitié de L après les appels récursifs. Par conséquent, la boucle sélectionne à chaque itération le plus petit élément non encore étudié et l'ajoute à ; est donc une liste non triée de plus en plus contenant tous les éléments deleft
right
while
result
result
left
etright
. L'inverse est une version triée de façon non décroissante de , qui est le résultat renvoyé - et souhaité -.Quant à l'exécution, comptons les comparaisons d'éléments et listons les opérations (qui dominent l'exécution de manière asymptotique). Les listes de longueur inférieure à deux ne provoquent ni l'un ni l'autre. Pour les listes de longueur , nous avons ces opérations causées par la préparation des entrées pour les appels récursifs, celles des appels récursifs eux-mêmes plus la boucle et une . Les deux paramètres récursifs peuvent être calculés avec au plus n opérations de liste chacune. La boucle est exécutée exactement n fois et chaque itération provoque au plus une comparaison d'éléments et exactement deux opérations de liste. La finale peut être implémentée pour utiliser 2 nn>1 n n 2n opérations de liste - chaque élément est supprimé de l'entrée et placé dans la liste de sortie. Par conséquent, le nombre d'opérations remplit la récurrence suivante:
while
reverse
while
reverse
Comme est clairement non décroissant, il suffit de considérer n = 2 k pour une croissance asymptotique. Dans ce cas , la récurrence se simplifie pourT n=2k
Par le théorème maître, nous obtenons qui s'étend à l'exécution de .T∈Θ(nlogn)
mergesort
Niveau ultra bas
Considérez cette implémentation (généralisée) de Mergesort dans Isabelle / HOL :
Cela comprend déjà des preuves de bonne définition et de résiliation. Trouvez ici une preuve d'exactitude (presque) complète .
Pour le "runtime", c'est-à-dire le nombre de comparaisons, une récurrence similaire à celle de la section précédente peut être mise en place. Au lieu d'utiliser le théorème maître et d'oublier les constantes, vous pouvez également l'analyser pour obtenir une approximation qui est asymptotiquement égale à la vraie quantité. Vous pouvez trouver l'analyse complète dans [1]; voici un aperçu (il ne correspond pas nécessairement au code Isabelle / HOL):
Comme ci-dessus, la récurrence du nombre de comparaisons est
Utilisation de différences imbriquées avant / arrièrefn en
qui, avec la formule de Perron, nous amène à
Évaluation de⊟(s)
la source
Dijkstra's«Une discipline de programmation» de consiste à analyser et à prouver des algorithmes et à concevoir pour la prouvabilité. Dans la préface de ce livre, Dijkstra explique comment un mini-langage construit très simple et correctement conçu pour être analysé suffit pour expliquer formellement de nombreux algorithmes:
Plus tard, il explique à quel point il a réussi à obtenir sa mini-langue.
la source