Un filtre Bloom permet de suivre efficacement si différentes valeurs ont déjà été rencontrées lors du traitement. Lorsqu'il existe de nombreux éléments de données, un filtre Bloom peut entraîner une économie de mémoire significative sur une table de hachage. La principale caractéristique d'un filtre Bloom, qu'il partage avec une table de hachage, est qu'il dit toujours "pas nouveau" si un élément n'est pas nouveau, mais il y a une probabilité non nulle qu'un élément soit marqué comme "pas nouveau" "même quand c'est nouveau.
Existe-t-il un "filtre anti-Bloom", qui a le comportement inverse?
En d'autres termes: existe-t-il une structure de données efficace qui dit "nouveau" si un article est nouveau, mais qui pourrait également dire "nouveau" pour certains articles qui ne sont pas nouveaux?
Garder tous les éléments précédemment vus (par exemple, dans une liste chaînée triée) satisfait la première exigence mais peut utiliser beaucoup de mémoire. J'espère que cela est également inutile, compte tenu de la deuxième condition assouplie.
Pour ceux qui préfèrent un traitement plus formel, écrivez si le filtre Bloom pense que est nouveau, sinon, et écrivez si est vraiment nouveau et sinon.n ( x ) = 1 x n ( x ) = 0
Alors ; ; ; , pour quelque .
Je demande: existe-t-il une structure de données efficace, implémentant une fonction avec quelque 0 < β < 1 , telle que P r [ b ′ ( x ) = 0 | n ( x ) = 0 ] = β ; P r [ b ′ ( x ) = 0 | n ( x ) = 1 ] = 0 ; P r ; ?
Edit: Il semble que cette question ait été posée auparavant sur StackExchange, car /programming/635728 et /cstheory/6596 avec une gamme de réponses de "ne peut pas être fait "à travers" peut être fait, à un certain coût "à" c'est trivial à faire, en inversant les valeurs de ". Il n'est pas encore clair pour moi quelle est la "bonne" réponse. Ce qui est clair, c'est qu'un schéma de mise en cache LRU d'une certaine sorte (comme celui suggéré par Ilmari Karonen) fonctionne plutôt bien, est facile à mettre en œuvre et a entraîné une réduction de 50% du temps nécessaire à l'exécution de mon code.
la source
Réponses:
En allant avec l'idée de hachage de Patrick87, voici une construction pratique qui répond presque à vos exigences - la probabilité de confondre faussement une nouvelle valeur avec une ancienne n'est pas tout à fait nulle, mais peut être facilement rendue négligeable.
Choisissez les paramètres et k ; les valeurs pratiques pourraient être, disons, n = 128 et k = 16 . Soit H une fonction de hachage cryptographique sécurisée produisant (au moins) n + k bits de sortie.n k n=128 k=16 H n+k
Soit un tableau de 2 k chaînes de bits à n bits. Ce tableau stocke l'état du filtre, en utilisant un total de n 2 k bits. (Peu importe la façon dont ce tableau est initialisé; nous pouvons simplement le remplir de zéros ou de bits aléatoires.)a 2k n n2k
Pour ajouter une nouvelle valeur au filtre, calculez ix , où i désigne les k premiersbits et j désigne les suivantsi∥j=H(x) i k j bits suivants de H ( x ) . Soit a i = j .n H(x) ai=j
Pour tester si une valeur a été ajoutée au filtre, calculez i ′x′ , comme ci-dessus, et vérifiez si a i ′ = j ′ . Si oui, retournez vrai; sinon retournez false.i′∥j′=H(x′) ai′=j′
Revendication 1: La probabilité d'un résultat faussement positif (= nouvelle valeur faussement prétendu avoir été vu) est . Cela peut être rendu arbitrairement petit, à un coût modeste en espace de stockage, en augmentant n ; en particulier, pour n ≥ 128 , cette probabilité est essentiellement négligeable, étant en pratique bien inférieure à la probabilité d'un faux positif dû à un dysfonctionnement matériel.1/2n+k n n≥128
En particulier, après que valeurs distinctes ont été vérifiées et ajoutées au filtre, la probabilité qu'au moins un faux positif se soit produit est ( N 2 - N ) / 2 n + k + 1 . Par exemple, avec n = 128 et k = 16 , le nombre de valeurs distinctes nécessaires pour obtenir un faux positif avec une probabilité de 50% est d'environ 2 ( n + k ) / 2 = 2 72 .N (N2−N)/2n+k+1 n=128 k=16 2(n+k)/2=272
Allégation 2: La probabilité d'un faux négatif (= valeur ajoutée précédemment prétendument nouvelle) n'est pas supérieure à , où N est le nombre de valeurs distinctes ajoutées au filtre (ou, plus précisément, le nombre de valeurs distinctes ajoutées après que la valeur spécifique testée a été ajoutée le plus récemment au filtre).1−(1−2−k)N≈1−exp(−N/2k)<N/2k N
Ps. Pour mettre «négligeable petit» en perspective, le cryptage 128 bits est généralement considéré comme incassable avec la technologie actuellement connue. Obtenir un faux positif de ce schéma avec est aussi probable que quelqu'un devine correctement votre clé de chiffrement secrète 128 bits lors de sa première tentative . (Avec n = 128 et k = 16 , il est en fait environ 65 000 fois moins probable que cela.)n+k=128 n=128 k=16
Mais si cela vous laisse encore une sensation de nervosité irrationnelle, vous pouvez toujours passer à ; cela doublera vos besoins de stockage, mais je peux vous parier en toute sécurité toute somme que vous voudriez nommer que personne ne verra jamais de faux positif avec n = 256 - en supposant que la fonction de hachage n'est pas rompue, de toute façon.n=256 n=256
la source
Non, il n'est pas possible d'avoir une structure de données efficace avec ces propriétés, si vous voulez avoir la garantie que la structure de données dira "nouvelle" si elle est vraiment nouvelle (elle ne dira jamais, "jamais nouvelle" si il est en fait nouveau, aucun faux négatif autorisé). Une telle structure de données devra conserver toutes les données pour pouvoir répondre "pas nouveau". Voir la réponse de pents90 sur cstheory pour une justification précise.
En revanche, les filtres Bloom peuvent obtenir une garantie que la structure de données dira "pas nouveau" si elle n'est pas nouvelle, d'une manière efficace. En particulier, les filtres Bloom peuvent être plus efficaces que le stockage de toutes les données: chaque élément individuel peut être assez long, mais la taille du filtre Bloom évolue avec le nombre d'éléments, et non leur longueur totale. Toute structure de données pour votre problème devra évoluer avec la longueur totale des données, pas le nombre d'éléments de données.
la source
Et juste une table de hachage? Lorsque vous voyez un nouvel élément, consultez la table de hachage. Si l'emplacement de l'article est vide, retournez "nouveau" et ajoutez l'article. Sinon, vérifiez si la place de l'article est occupée par l'article. Si c'est le cas, retournez "pas nouveau". Si l'emplacement est occupé par un autre élément, retournez "nouveau" et écrasez l'emplacement avec le nouvel élément.
Vous obtiendrez certainement toujours correctement "Nouveau" si vous n'avez jamais vu le hachage de l'élément auparavant. Vous obtiendrez certainement toujours correctement "Pas nouveau" si vous n'avez vu le hachage de l'élément que lorsque vous avez vu le même élément. La seule fois où vous obtiendrez «Nouveau» lorsque la bonne réponse est «Pas nouveau» est si vous voyez l'élément A, puis voir l'élément B, puis voir à nouveau l'élément A, et les hachages A et B font la même chose. Surtout, vous ne pouvez jamais obtenir «Pas nouveau» de manière incorrecte.
la source
Dans le cas où l'univers des éléments est fini, alors oui: utilisez simplement un filtre de floraison qui enregistre quels éléments sont hors de l'ensemble, plutôt que dans l'ensemble. (C'est-à-dire, utilisez un filtre de floraison qui représente le complément de l'ensemble d'intérêt.)
Un endroit où cela est utile est d'autoriser une forme limitée de suppression. Vous gardez deux filtres de floraison. Ils commencent vides. Lorsque vous insérez des éléments, vous les insérez dans le filtre de floraison A. Si vous souhaitez par la suite supprimer un élément, vous insérez cet élément dans le filtre de floraison B. Il n'y a aucun moyen d'annuler la suppression. Pour effectuer une recherche, vous effectuez d'abord une recherche dans le filtre de floraison A. Si vous ne trouvez aucune correspondance, l'élément n'a jamais été inséré (avec probabilité 1). Si vous trouvez une correspondance, l'élément peut (ou non) avoir été inséré. Dans ce cas, vous effectuez une recherche dans le filtre de floraison B. Si vous ne trouvez aucune correspondance, l'élément n'a jamais été supprimé. Si vous trouvez une correspondance dans le filtre de floraison B, l'élément a probablement été inséré, puis supprimé.
Cela ne répond pas vraiment à votre question, mais, dans ce cas limité, le filtre de floraison B exécute exactement le comportement de "filtre anti-floraison" que vous recherchez.
Les chercheurs sur le filtre Real Bloom utilisent des moyens beaucoup plus efficaces de représenter la suppression, voir la page de la publication de Mike Mitzenmacher .
la source
Je veux juste ajouter ici, que si vous êtes dans une situation chanceuse, que vous connaissez toutes les valeursvje que vous pourriez voir; alors vous pouvez utiliser un filtre de floraison de comptage.
Un exemple pourrait être les adresses IP, et vous voulez savoir à chaque fois que vous en voyez une que vous n'avez jamais vue auparavant. Mais c'est toujours un ensemble fini, donc vous savez à quoi vous attendre.
La solution réelle est simple:
Vous pouvez donc avoir des valeurs de «faux positifs» qui étaient en fait anciennes, mais reconnues comme nouvelles. Cependant, vous n'obtiendrez jamais «pas nouveau» pour une nouvelle valeur, car sa valeur sera toujours dans tous les emplacements, et personne d'autre n'aurait pu l'enlever.
la source