Complexité de l'algorithme de shuffle de Fisher-Yates

15

Cette question concerne l'algorithme de Fisher-Yates pour renvoyer un mélange aléatoire d'un tableau donné. La page Wikipedia dit que sa complexité est O (n), mais je pense que c'est O (n log n).

Dans chaque itération i, un entier aléatoire est choisi entre 1 et i. La simple écriture de l'entier en mémoire est O (log i), et comme il y a n itérations, le total est

O (log 1) + O (log 2) + ... + O (log n) = O (n log n)

ce qui n'est pas mieux l'algorithme naïf. Est-ce que j'ai râté quelque chose?

Remarque: L'algorithme naïf consiste à attribuer à chaque élément un nombre aléatoire dans l'intervalle (0,1), puis à trier le tableau en fonction des nombres attribués.

Tomer Vromen
la source

Réponses:

24

Je soupçonne qu'ici, comme dans la plupart des algorithmes, le coût de lecture et d'écriture des nombres de bits est supposé être une constante. C'est un péché mineur, tant que vous ne vous laissez pas emporter et effondrez P et PSPACE par accident .O(Journaln)

Suresh Venkat
la source
4
Bien qu'il s'agisse en effet d'un "péché mineur", je pense que c'est un péché majeur de la pédagogie TCS que cela ne soit jamais mentionné explicitement! Chaque étudiant CS découvre cela par lui-même et pense que quelque chose d'important ne va pas jusqu'à ce qu'on leur dise que tout le monde le sait mais que personne n'en parle. De plus, n'y avait-il pas un brouhaha il y a quelques années lorsque quelqu'un a exploité le modèle O (log n) pour donner un algorithme de temps sub-cubique pour un problème célèbre qui était supposé être Omega (n ^ 3)? Cela a-t-il déjà été résolu?
randomwalker
2
Je ne connais pas le brouhaha dont vous parlez. Quant à ne pas le mentionner, vous avez certainement raison. Après avoir lu le post de Jeff Erickson pour la première fois, je tiens à prouver P = PSPACE dans ma classe de géométrie juste pour les coups de pied :)
Suresh Venkat
1
Merci d'avoir répondu. Je n'ai jamais su que c'était un gros problème. Le lien fournit une bonne lecture.
Tomer Vromen
1
Conclusion: toujours rendre votre modèle explicite.
Jukka Suomela
2
Je pense que la principale raison pour laquelle nous laissons les opérations de bit être à temps constant est que (en temps polynomial) vous pouvez programmer une table de recherche d'accès à temps constant pour toutes les paires d' opérandes O ( log n ) bits, pour la plupart modèles de calcul "modernes". Il n'y a rien de "pécheur" à ce sujet ... pour moi, je vois cette propriété comme une propriété qui peut simplement être assumée sans perte de généralité. O(Journaln)O(Journaln)
Ryan Williams
17

Le modèle standard de calcul suppose que les opérations arithmétiques sur des entiers O (log n) bits peuvent être exécutées en temps constant, car ces opérations sont généralement remises au matériel. Ainsi, dans l'algorithme de Fisher-Yates, «écrire l'entier i en mémoire» ne prend que O (1).

Bien sûr, il est parfaitement significatif d'analyser l'algorithme en termes d'opérations sur les bits, mais le modèle de coût en bits est moins prédictif du comportement réel. Même la boucle simple for i = 1 to n: print(i)nécessite des opérations sur O (n log n) bits.

Jeffε
la source
Joli point avec la boucle. Jamais remarqué que ...
Tomer Vromen
8

Ceci est une réponse à "[l'algorithme de Fisher-Yates] n'est pas meilleur que l'algorithme naïf. Suis-je en train de manquer quelque chose ici?" que vous avez posé dans la question.

Dans votre algorithme "naïf" qui utilise des nombres réels: combien de bits de précision utilisez-vous? Si vous comptez la complexité des bits (comme vous semblez le faire pour Fisher-Yates), et que l'algorithme utilise k bits aléatoires pour les nombres réels, alors son temps d'exécution serait Ω (kn log n), car en comparant deux k- les nombres réels binaires prennent du temps Ω (k). Mais k doit être d'au moins Ω (log n) pour éviter que deux éléments soient mappés au même nombre réel, ce qui signifie que l'algorithme prend du temps Ω (n log 2 n), ce qui est plus lent que le shuffle de Fisher-Yates par un facteur de log n.

Si vous comptez simplement le nombre d'opérations arithmétiques et de comparaison et ignorez leur complexité en bits, alors Fisher-Yates est Θ (n) et votre algorithme est Θ (n log n), toujours un facteur de log n à part.

ShreevatsaR
la source
Je soupçonnais que l'algorithme "naïf" avait cette implicite k ...
Tomer Vromen
1
L'algorithme "naïf" peut être implémenté proprement en temps linéaire comme suit. Attribuez à chaque élément un entier aléatoire compris entre 1 et n ^ 3, puis triez les nombres en temps O (n) via le tri radix. (Avec une forte probabilité, deux éléments n'obtiendront pas le même nombre aléatoire. S'il y a des doublons,
remaniez-
@JeffE: Merci! C'est très propre et a la même complexité que Fisher-Yates. Après avoir posté cela, je sentais en fait que l'algorithme «naïf» ne devrait pas être pire ... J'ai manqué le fait que les nombres à n k bits peuvent être triés en O (nk), sans avoir besoin de O (nklog n). Mais je suppose que Knuth-Fisher-Yates est encore meilleur dans les constantes: il nécessite exactement (log n!) Des bits aléatoires - un entier aléatoire de 1 à n, puis de 1 à n-1, etc. - ce qui est optimal (au lieu de 3n log n), et cela peut être fait sur place avec seulement une mémoire supplémentaire constante.
ShreevatsaR
6

Les entiers n'ont rien de spécial pour ce problème.

Par exemple, les tables de hachage (stockant tout type de valeurs) ne sont pas O (1) temps d'accès si la fonction de hachage doit lire la valeur entière pour calculer son hachage. n éléments uniques ont besoin de log n bits chacun en moyenne pour représenter, quelle que soit l'intelligence de votre représentation, et toute fonction de hachage qui lit toute son entrée prendra donc au moins autant de temps à calculer. En pratique, ils sont plus rapides que les arbres rouge-noir, mais asymptotiquement ils ne sont pas meilleurs.

Le brouhaha référencé par randomwalker concernait un article POPL 2008 ( http://portal.acm.org/citation.cfm?doid=1328438.1328460 ), discuté ici: http://blog.computationalcomplexity.org/2009/05/shaving- logs-with-unit-cost.html

Dans ce post, Lance Fortnow décrit comment en tant qu'étudiant, il s'est plaint que le tri nécessite vraiment n log ^ 2 n temps si nous devons lire tous les log n bits de deux éléments afin de les comparer, ce qui semble une objection raisonnable.

Dave Doty
la source
Je n'ai pas l'auteur de l'article de blog. Il se plaint que le tri est en fait O (n log ^ 2 n), mais dit ensuite que le papier est solide?
Tomer Vromen
Le papier est solide (c'est-à-dire non faux) en ce qu'il existe un modèle dans lequel les opérations arithmétiques prennent un temps unitaire, et dans ce modèle l'algorithme du papier est le premier à réaliser des opérations o (n ^ 3).
Dave Doty
Je ne reçois pas l'objection O (n log ^ 2 n) car en termes de bits, l'entrée elle-même est de taille O (n log n). En passant, comme note de côté, le niveau de qualité des commentaires sur le blog de complexité était tellement plus élevé que ....
arnab
4

La page Wikipedia dit que sa complexité est O (n), mais je pense que c'est O (n log n).

En fait, O (n log n) est une borne inférieure pour ce problème dans les modèles où le tri est O (n log n). Si toutes les permutations sont également probables, l'algorithme en fonction des flux aléatoires aux permutations doit être surjectif. Il y en a n! permutations donc dans quelque chose comme un modèle d'arbre de décision, il y a des branches de longueur au moins O (log n!) = O (n log n).

1-ϵO(ϵ)

Per Vognsen
la source
3

Dans TCS, nous considérons - sauf indication contraire explicite - la complexité d'une machine de Turing. Bien que cela soit correct à des fins théoriques, les résultats ne sont pas très utiles dans la pratique car nous implémentons différents modèles de machine (c'est-à-dire des approximations finies) dans le matériel. Il est donc possible de demander la complexité de ces modèles. Par exemple, nous supposons généralement que les machines à registres (similaires aux CPU réels) peuvent effectuer des opérations atomiques sur deux registres en temps constant - c'est ce qui aurait pu être utilisé ici.

En bref: vous pensez en termes de MT, les auteurs de l'article en termes de RM. Vous avez tous les deux raison.

Raphael
la source