web-dev-qa-db-fra.com

Temps d'amortissement constant

Qu'entend-on par "temps constant d'amortissement" lorsqu'on parle de la complexité temporelle d'un algorithme?

385
VarunGupta

Temps amorti expliqué en termes simples:

Si vous faites une opération un million de fois, vous ne vous souciez pas vraiment du pire ou du pire cas de cette opération. Ce qui compte, c'est de savoir combien de temps il faut au total pour répéter l'opération un million de fois. .

Ainsi, peu importe si l'opération est très lente de temps en temps, à condition que "de temps en temps" soit suffisamment rare pour que la lenteur disparaisse. Le terme essentiellement amorti signifie "temps moyen pris par opération, si vous effectuez plusieurs opérations". Le temps amorti ne doit pas nécessairement être constant. vous pouvez avoir un temps amorti linéaire et logarithmique ou autre chose.

Prenons l'exemple de mats d'un tableau dynamique, auquel vous ajoutez de manière répétée de nouveaux éléments. L'ajout d'un élément prend normalement un temps constant (c'est-à-dire O(1)). Mais chaque fois que le tableau est plein, vous allouez deux fois plus d'espace, copiez vos données dans la nouvelle région et libérez l'ancien. En supposant que les allocations et les arrêts soient exécutés en temps constant, ce processus d’agrandissement prend O(n) time, où n est la taille actuelle du tableau.

Ainsi, chaque fois que vous agrandissez, vous prenez environ deux fois plus de temps que le dernier agrandissement. Mais vous avez également attendu deux fois plus longtemps avant de le faire! Le coût de chaque agrandissement peut ainsi être "réparti" entre les insertions. Cela signifie qu'à long terme, le temps total nécessaire à l'ajout de m éléments au tableau est O(m), et donc le temps amorti (c'est-à-dire le temps par insertion) est de O(1). .

734
Artelius

Cela signifie qu'avec le temps, le pire des scénarios sera par défaut à O (1) ou à temps constant. Un exemple courant est le tableau dynamique. Si nous avons déjà alloué de la mémoire pour une nouvelle entrée, l'ajouter sera O (1). Si nous ne l'avons pas alloué, nous le ferons en allouant, disons, le double du montant actuel. Cette insertion particulière ne sera pas ni O (1), mais plutôt quelque chose d'autre.

Ce qui est important, c’est que l’algorithme garantisse qu’après une séquence d’opérations, les opérations coûteuses seront amorties, ce qui rendra l’ensemble de l’opération O (1).

Ou en termes plus stricts,

Il existe une constante c, telle que pour chaque séquence d'opérations (également une se terminant par une opération coûteuse) de longueur L, le temps n'est pas supérieur à c * L (Merci Rafał Dowgird )

55
Mats Fredriksson

Pour développer une façon intuitive de penser à ce sujet, considérez l'insertion d'éléments dans tableau dynamique (par exemple, std::vector en C++). Traçons un graphique qui montre la dépendance du nombre d'opérations (Y) nécessaires pour insérer N éléments dans un tableau:

plot

Les parties verticales du graphe noir correspondent à des réallocations de mémoire afin d'élargir un tableau. Nous pouvons voir ici que cette dépendance peut être représentée grossièrement par une ligne. Et cette équation de ligne est Y=C*N + b (C est constante, b = 0 dans notre cas). Par conséquent, nous pouvons dire que nous devons dépenser C*N opérations en moyenne pour ajouter N éléments au tableau, ou C*1 opérations pour ajouter un élément (temps constant amorti).

18
Megamozg

J'ai trouvé l'explication utile ci-dessous, après lecture répétée 3 fois:

Source: https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_Array

"Tableau dynamique

Analyse amortie de l'opération Push pour un tableau dynamique

Considérez un tableau dynamique dont la taille augmente à mesure que d’autres éléments y sont ajoutés, tels que ArrayList en Java. Si nous démarrions avec un tableau dynamique de taille 4, il faudrait un temps constant pour insérer quatre éléments dessus. Il serait toutefois plus long d'insérer un cinquième élément dans ce tableau, car le tableau devrait créer un nouveau tableau dont la taille est égale à deux fois la taille actuelle (8), copier les anciens éléments dans le nouveau tableau, puis ajouter le nouvel élément. Les trois opérations Push suivantes prendraient de la même manière un temps constant, puis l’ajout ultérieur nécessiterait un autre doublement lent de la taille de la matrice.

En général, si nous considérons un nombre arbitraire de poussées n dans un tableau de taille n, nous remarquons que les opérations de Push prennent un temps constant, à l'exception du dernier qui nécessite O(n) pour effectuer l'opération de doublage de taille. . Comme il y avait n opérations au total, nous pouvons prendre la moyenne de ceci et trouver que pour pousser des éléments sur le tableau dynamique prend: O (n/n) = O (1), temps constant. "

À ma compréhension, comme une histoire simple:

Supposons que vous avez beaucoup d'argent. Et vous voulez les empiler dans une pièce. Et vous avez de longues mains et de longues jambes, aussi longtemps que vous en avez besoin maintenant ou à l'avenir. Et, vous devez tout remplir dans une seule pièce, il est donc facile de la verrouiller.

Donc, vous allez directement au bout/au coin de la pièce et commencez à les empiler. Au fur et à mesure que vous les empilez, la pièce manquera lentement d'espace. Cependant, au fur et à mesure que vous remplissez, il était facile de les empiler. Vous avez l'argent, mettez l'argent. Facile. C'est O (1). Nous n'avons pas besoin de déplacer de l'argent précédent.

Une fois que la pièce est à court d'espace. Nous avons besoin d'une autre pièce plus grande. Ici, il y a un problème, étant donné que nous ne pouvons avoir qu'une seule pièce et donc qu'une seule serrure, nous devons transférer tout l'argent existant dans cette pièce dans la nouvelle pièce plus grande. Alors, déplacez tout l'argent, de la petite pièce à la pièce plus grande. Autrement dit, empilez-les tous à nouveau. Nous avons donc besoin de déplacer tout l'argent précédent. Donc, c'est O (N). (en supposant que N est le compte total de l'argent de l'argent précédent)

En d’autres termes, c’était facile jusqu’à N, une seule opération, mais lorsque nous devons déménager dans une salle plus grande, nous effectuons N opérations. Donc, en d’autres termes, si nous sommes en moyenne, c’est 1 insertion au début et 1 déplacement supplémentaire lorsque vous vous déplacez dans une autre pièce. Total de 2 opérations, un insert, un mouvement.

En supposant que N soit grand comme 1 million, même dans la petite pièce, les 2 opérations comparées à N (1 million) n’est pas vraiment un nombre comparable, donc on le considère comme constant ou O (1).

En supposant que nous fassions tout ce qui précède dans une autre pièce plus grande et que nous devions déménager. C'est encore le même. disons, N2 (disons, 1 milliard) est le nouveau montant du compte d'argent dans la plus grande pièce

Donc, nous avons N2 (qui inclut N de précédent puisque nous passons tous de petite à grande pièce)

Nous n’avons toujours besoin que de 2 opérations: l’une est insérée dans une pièce plus grande, puis une autre opération pour passer à une pièce encore plus grande.

Donc, même pour N2 (1 milliard), il s'agit de 2 opérations pour chacune. ce qui n'est plus rien. Donc, il est constant, ou O (1)

Donc, lorsque le N augmente de N à N2 ou autre, peu importe. Il est toujours constant ou O(1) opérations requises pour chacun des N.


Supposons maintenant que vous avez N comme 1, très petit, le compte d'argent est petit et que vous avez une très petite pièce, qui ne peut contenir qu'un seul compte d'argent.

Dès que vous remplissez l'argent dans la pièce, la pièce est remplie.

Lorsque vous vous rendez dans la pièce la plus grande, supposez qu’elle ne peut contenir qu’une somme d’argent supplémentaire, soit un total de deux comptes d’argent. Cela signifie que le précédent a déplacé de l'argent et 1 de plus. Et encore c'est rempli.

De cette façon, le N croît lentement et il n’est plus constant O (1), puisque nous déplaçons tout l’argent de la pièce précédente, mais ne pouvons contenir qu’un seul argent supplémentaire.

Après 100 fois, la nouvelle salle correspond à 100 pièces d'argent de la précédente et 1 argent supplémentaire qu'elle peut accueillir. C’est O (N), puisque O (N + 1) est O (N), c’est-à-dire que le degré de 100 ou 101 est le même, les deux sont des centaines, contrairement à l’histoire précédente de, des millions à des millions et des milliards à des milliards. .

Il s’agit donc d’un moyen inefficace d’allouer des salles (ou mémoire/RAM) à notre argent (variables).


Donc, une bonne solution consiste à allouer plus de place, avec des puissances de 2.

1ère taille de la chambre = correspond à 1 compte d'argent
2ème taille de la chambre = correspond à 4 comptes d'argent
3ème taille de la pièce = correspond à 8 pièces en argent
4ème taille de la pièce = correspond à 16 fois le montant
5ème taille de la pièce = correspond à 32 pièces
6ème taille de la chambre = correspond à 64 pièces en argent
7ème taille de la pièce = correspond à 128 pièces en argent
8ème taille de la pièce = correspond à 256 pièces en argent
9ème taille de la pièce = correspond à 512 pièces en argent
10ème pièce = 1024 pièces
Onzième taille de la pièce = 2 048 comptes d’argent
...
16ème taille de la chambre = correspond à 65 536 pièces en argent
...
32ème chambre = 4 294 967 296 comptes en argent
...
64ème taille de la chambre = correspond à 18 446 744 073 709 551 616

Pourquoi est-ce mieux? Parce qu'il semble croître lentement au début, et plus vite par la suite, comparé à la quantité de mémoire de notre RAM.

Ceci est utile car, dans le premier cas, même s’il est bon, la quantité totale de travail à effectuer par argent est fixe (2) et non comparable à la taille de la pièce (N). gros (1 million) que nous ne pourrons peut-être pas utiliser pleinement si nous pouvons avoir autant d’argent à économiser dans le premier cas.

Cependant, dans le dernier cas, puissance de 2, il grandit dans les limites de notre RAM. Ainsi, en augmentant de puissance de 2, l’analyse Armotisée reste constante et elle est adaptée aux besoins limités du RAM que nous avons à ce jour.

12

Les explications ci-dessus s’appliquent à l’analyse globale, l’idée de prendre "une moyenne" sur plusieurs opérations. Je ne suis pas sûr de savoir comment ils s'appliquent à la méthode Bankers ou à l'analyse des méthodes d'analyse par les physiciens.

Maintenant. Je ne suis pas tout à fait sûr de la bonne réponse. Mais cela aurait à voir avec la condition principale des méthodes des deux physiciens + banquier:

(Somme du coût de fonctionnement amorti)>> (Somme du coût de revient réel des opérations).

La principale difficulté à laquelle je suis confronté est que, étant donné que les coûts d’exploitation asymptotiques amortis diffèrent des coûts normaux asymptotiques, je ne sais pas comment évaluer l’importance des coûts amortis.

C'est quand quelqu'un me donne un coût amorti, je sais que ce n'est pas la même chose que le coût normal asymptotique. Quelles conclusions puis-je tirer du coût amorti?

Étant donné que certaines opérations sont surchargées alors que d'autres sont sous-facturées, une hypothèse pourrait être que le calcul du coût amorti de chaque opération n'aurait aucun sens.

Par exemple, pour un tas de fibonacci, citer le coût amorti de Decreasing-Key juste pour être O(1) n'a pas de sens puisque les coûts sont réduits du fait que "le travail effectué par les opérations antérieures augmente le potentiel du tas."

OR

Nous pourrions avoir une autre hypothèse qui motive les coûts amortis comme suit:

  1. Je sais que l'opération coûteuse va être précédée d'opérations MULTIPLE LOW-COST.

  2. À des fins d’analyse, je vais surcharger certaines opérations à faible coût, de sorte que leur coût asymétrique ne change pas.

  3. Avec cette augmentation des opérations à faible coût, je peux PROUVER QU'UNE OPÉRATION ÉLEVÉE a un COÛT ASYMPTOTIQUE PLUS PETIT.

  4. Ainsi, j’ai amélioré/diminué la LIAISON ASYMPTOTIQUE du coût de n opérations.

Ainsi, l'analyse du coût amorti + les limites du coût amorti ne s'appliquent désormais qu'aux opérations coûteuses. Les opérations bon marché ont le même coût amorti asymptotique que leur coût asymptotique normal.

1
Misraji