Le temps de la complexité de l'accès à un Python dict
Je suis en train d'écrire un simple programme en Python.
Mon programme semble souffrir de linéaire de l'accès à des dictionnaires,
son exécution se développe de façon exponentielle, même si l'algorithme est quadratique.
J'utilise un dictionnaire pour memoize valeurs. Ce qui semble être un goulot d'étranglement.
Les valeurs que je suis de hachage sont des n-uplets de points.
Chaque point est: (x,y), 0 <= x,y <= 50
Chaque clé dans le dictionnaire est: Un n-uplet de 2 à 5 points: ((x1,y1),(x2,y2),(x3,y3),(x4,y4))
Les touches sont lu de nombreuses fois plus souvent qu'ils sont écrits.
Suis-je correct que python dicts souffrent de linéaire temps d'accès à de telles données?
Autant que je sache, les jeux ont garanti logarithmique temps d'accès.
Comment puis-je simuler des dicts à l'aide des ensembles(ou quelque chose de similaire) en Python?
modifier conformément à la demande de plusieurs, voici un (simplifié) de la version de la memoization fonction:
def memoize(fun):
memoized = {}
def memo(*args):
key = args
if not key in memoized:
memoized[key] = fun(*args)
return memoized[key]
return memo
- Quelles preuves avez-vous pour cela? Pouvez-vous fournir votre rendement réel des chiffres? Profil de résultats? Vous êtes probablement à la recherche dans le mauvais endroit pour votre problème. Merci donc de documenter votre problème avant de faire des suppositions quant à la cause.
- Je lance le tout à travers le python profiler. Le memoization fonction prend de façon exponentielle plus même si il y a polynomialement différentes entrées qu'elle peut prendre. Je vais poster profileur de données si vous le souhaitez.
- Pouvez-vous nous un exemple de code pour le memoization fonction? Vous pouvez aussi essayer d'écrire un test rapide d'application, générant une charge de hachages pour vos données et en comptant le nombre de collisions (il ne devrait pas prendre de temps en fonction de la façon dont les hachages en python travail)
- I. e. avec O(N**5) entrées il prend 2 secondes avec N = 8 et 4 secondes avec N = 9.
- Je sais ce que l'exponentielle est, merci. Cependant, les dictionnaires en général il suffit de ne pas se comporter comme ça. Nous avons pu voir un exemple de code ici, afin que nous puissions voir ce que vous êtes en train de faire différemment de provoquer un tel comportement étrange.
- Veuillez coller le réel memoization fonction, pas une version simplifiée. Vous pouvez avoir caché le bug lors de la simplification.
- -1 pour poser une question sans réponse. Un jeu de données de test sur le long avec complet profilable code (avec le profilage des résultats) serait nécessaire.
- -1 pour poser une question sans suffisamment d'informations pour évaluer correctement le problème, et puis ce qui suggère que d'autres demandent plus d'informations sont "impoli". Vous êtes le seul à demander de l'aide, quand les gens offrent à vous aider à demander pour plus de renseignements, ils ne sont pas "impoli", mais vous êtes certainement impoli pour faire ce genre de ad hominem affirmation. De toute évidence, vous ne savez pas toutes les informations nécessaires pour répondre à la question que vous nous avez fournis, ou vous avez déjà répondu pour vous-même.
Vous devez vous connecter pour publier un commentaire.
Voir Le Temps De La Complexité. Le python dict est une table de hachage, son pire des cas est donc O(n) si la fonction de hachage est mauvais et les résultats dans un grand nombre de collisions. Cependant c'est un cas très rare où chaque élément ajouté est le même hachage et est donc ajouté à la même chaîne qui, pour un grand Python la mise en œuvre serait extrêmement peu probable. La durée moyenne de la complexité est bien sûr O(1).
La meilleure méthode serait de vérifier et de prendre un regard sur les hashs des objets que vous utilisez. Le Disponible Dict utilise int PyObject_Hash (PyObject *o) qui est l'équivalent de
hash(o)
.Après une vérification rapide, je n'ai pas encore réussi à trouver deux tuples de hachage à la même valeur, ce qui pourrait indiquer que la recherche est O(1)
CodePad (Disponible pour 24 heures)
(x, y)
points clés, c'est à l'aide de((x0,y0),(x1, y1))
jusqu'à((x0,y0), ..., (x4, y4))
. Il asum(51**(n*2) for n in range(2,6))
(c'est à dire 119088209375236404) clés possibles, pas51**2
Vous ne sont pas correctes.
dict
d'accès est peu probable que votre problème ici. Il est presque certainement O(1), sauf si vous avez une drôle d'entrées ou une très mauvaise fonction de hachage. Coller un exemple de code à partir de votre application pour un meilleur diagnostic.Il serait plus facile de faire des suggestions si vous avez fourni un exemple de code et de données.
Accès au dictionnaire est peu probable d'être un problème tant que l'opération est O(1) en moyenne, et O(N) amorti pire des cas. Il est possible que le construit-dans les fonctions de hachage rencontrez des collisions pour vos données. Si vous rencontrez des problèmes avec la a la fonction de hachage, vous pouvez fournir votre propre.
Vous pouvez remplacer le __hash__ méthode dans votre classe pour mettre en œuvre une coutume fonction de hachage comme ceci:
En fonction de votre apparence, vous pourriez être en mesure de venir avec un plus rapide fonction de hachage qui a moins de collisions que la fonction standard. Il est toutefois peu probable. Voir la Python page Wiki sur les Clés de Dictionnaire pour plus d'informations.
C'est la preuve d'un bug dans votre memoization méthode.
Pour répondre à vos questions:
T1: """Suis-je correct que python dicts souffrent de linéaire temps d'accès à de telles données?"""
A1: Si vous voulez dire que la moyenne de recherche en temps est O(N) où N est le nombre d'entrées dans le dict, il est très probable que vous avez tort. Si vous avez raison, la communauté Python voudrais bien savoir dans quelles circonstances vous sont correctes, de sorte que le problème peut être atténué ou au moins averti. Ni "exemple de code", ni "simplifiée" code sont utiles. Veuillez montrer le code et les données permettant de reproduire le problème. Le code doit être instrumentée avec des choses comme le nombre de dict éléments et le nombre de dict accès pour chaque P, où P est le nombre de points à la clé (2 <= P <= 5)
T2: """autant Que je sache, les jeux ont garanti logarithmique temps d'accès.
Comment puis-je simuler des dicts à l'aide des ensembles(ou quelque chose de similaire) en Python?"""
A2: les Jeux ont garanti logarithmique temps d'accès dans quel contexte? Il n'y a aucune garantie pour les implémentations de Python. Récente Disponible versions en fait, l'utilisation d'un coupe-bas dict mise en œuvre (touches, pas de valeurs), de sorte que l'attente est en moyenne de O(1) comportement. Comment pouvez-vous simuler dicts avec des décors ou quelque chose de similaire dans n'importe quelle langue? Réponse courte: avec une extrême difficulté, si vous voulez une fonctionnalité au-delà de
dict.has_key(key)
.Comme d'autres l'ont souligné, l'accès à dicts en Python est rapide. Ils sont probablement le meilleur huilé structure de données dans la langue, compte tenu de leur rôle central. Le problème se situe ailleurs.
Combien de n-uplets sont vous memoizing? Avez-vous envisagé l'empreinte mémoire? Peut-être que vous passez tout votre temps dans l'allocateur de mémoire ou la pagination de la mémoire.