RetouchedBloomFilter.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:12k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  *
  3.  * Copyright (c) 2005, European Commission project OneLab under contract 034819 (http://www.one-lab.org)
  4.  * All rights reserved.
  5.  * Redistribution and use in source and binary forms, with or 
  6.  * without modification, are permitted provided that the following 
  7.  * conditions are met:
  8.  *  - Redistributions of source code must retain the above copyright 
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  *  - Redistributions in binary form must reproduce the above copyright 
  11.  *    notice, this list of conditions and the following disclaimer in 
  12.  *    the documentation and/or other materials provided with the distribution.
  13.  *  - Neither the name of the University Catholique de Louvain - UCL
  14.  *    nor the names of its contributors may be used to endorse or 
  15.  *    promote products derived from this software without specific prior 
  16.  *    written permission.
  17.  *    
  18.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  19.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  20.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  21.  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  22.  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  23.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
  24.  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  25.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  26.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  28.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31. /**
  32.  * Licensed to the Apache Software Foundation (ASF) under one
  33.  * or more contributor license agreements.  See the NOTICE file
  34.  * distributed with this work for additional information
  35.  * regarding copyright ownership.  The ASF licenses this file
  36.  * to you under the Apache License, Version 2.0 (the
  37.  * "License"); you may not use this file except in compliance
  38.  * with the License.  You may obtain a copy of the License at
  39.  *
  40.  *     http://www.apache.org/licenses/LICENSE-2.0
  41.  *
  42.  * Unless required by applicable law or agreed to in writing, software
  43.  * distributed under the License is distributed on an "AS IS" BASIS,
  44.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  45.  * See the License for the specific language governing permissions and
  46.  * limitations under the License.
  47.  */
  48. package org.apache.hadoop.util.bloom;
  49. import java.io.DataInput;
  50. import java.io.DataOutput;
  51. import java.io.IOException;
  52. import java.util.ArrayList;
  53. import java.util.Collection;
  54. import java.util.Collections;
  55. import java.util.List;
  56. import java.util.Random;
  57. /**
  58.  * Implements a <i>retouched Bloom filter</i>, as defined in the CoNEXT 2006 paper.
  59.  * <p>
  60.  * It allows the removal of selected false positives at the cost of introducing
  61.  * random false negatives, and with the benefit of eliminating some random false
  62.  * positives at the same time.
  63.  * 
  64.  * <p>
  65.  * Originally created by
  66.  * <a href="http://www.one-lab.org">European Commission One-Lab Project 034819</a>.
  67.  * 
  68.  * @see Filter The general behavior of a filter
  69.  * @see BloomFilter A Bloom filter
  70.  * @see RemoveScheme The different selective clearing algorithms
  71.  * 
  72.  * @see <a href="http://www-rp.lip6.fr/site_npa/site_rp/_publications/740-rbf_cameraready.pdf">Retouched Bloom Filters: Allowing Networked Applications to Trade Off Selected False Positives Against False Negatives</a>
  73.  */
  74. public final class RetouchedBloomFilter extends BloomFilter
  75. implements RemoveScheme {
  76.   /**
  77.    * KeyList vector (or ElementList Vector, as defined in the paper) of false positives.
  78.    */
  79.   List<Key>[] fpVector;
  80.   /**
  81.    * KeyList vector of keys recorded in the filter.
  82.    */
  83.   List<Key>[] keyVector;
  84.   /**
  85.    * Ratio vector.
  86.    */
  87.   double[] ratio;
  88.   
  89.   private Random rand;
  90.   /** Default constructor - use with readFields */
  91.   public RetouchedBloomFilter() {}
  92.   
  93.   /**
  94.    * Constructor
  95.    * @param vectorSize The vector size of <i>this</i> filter.
  96.    * @param nbHash The number of hash function to consider.
  97.    * @param hashType type of the hashing function (see
  98.    * {@link org.apache.hadoop.util.hash.Hash}).
  99.    */
  100.   public RetouchedBloomFilter(int vectorSize, int nbHash, int hashType) {
  101.     super(vectorSize, nbHash, hashType);
  102.     this.rand = null;
  103.     createVector();
  104.   }
  105.   @Override
  106.   public void add(Key key) {
  107.     if (key == null) {
  108.       throw new NullPointerException("key can not be null");
  109.     }
  110.     int[] h = hash.hash(key);
  111.     hash.clear();
  112.     for (int i = 0; i < nbHash; i++) {
  113.       bits.set(h[i]);
  114.       keyVector[h[i]].add(key);
  115.     }
  116.   }
  117.   /**
  118.    * Adds a false positive information to <i>this</i> retouched Bloom filter.
  119.    * <p>
  120.    * <b>Invariant</b>: if the false positive is <code>null</code>, nothing happens.
  121.    * @param key The false positive key to add.
  122.    */
  123.   public void addFalsePositive(Key key) {
  124.     if (key == null) {
  125.       throw new NullPointerException("key can not be null");
  126.     }
  127.     int[] h = hash.hash(key);
  128.     hash.clear();
  129.     for (int i = 0; i < nbHash; i++) {
  130.       fpVector[h[i]].add(key);
  131.     }
  132.   }
  133.   /**
  134.    * Adds a collection of false positive information to <i>this</i> retouched Bloom filter.
  135.    * @param coll The collection of false positive.
  136.    */
  137.   public void addFalsePositive(Collection<Key> coll) {
  138.     if (coll == null) {
  139.       throw new NullPointerException("Collection<Key> can not be null");
  140.     }
  141.     
  142.     for (Key k : coll) {
  143.       addFalsePositive(k);
  144.     }
  145.   }
  146.   /**
  147.    * Adds a list of false positive information to <i>this</i> retouched Bloom filter.
  148.    * @param keys The list of false positive.
  149.    */
  150.   public void addFalsePositive(List<Key> keys) {
  151.     if (keys == null) {
  152.       throw new NullPointerException("ArrayList<Key> can not be null");
  153.     }
  154.     for (Key k : keys) {
  155.       addFalsePositive(k);
  156.     }
  157.   }
  158.   /**
  159.    * Adds an array of false positive information to <i>this</i> retouched Bloom filter.
  160.    * @param keys The array of false positive.
  161.    */
  162.   public void addFalsePositive(Key[] keys) {
  163.     if (keys == null) {
  164.       throw new NullPointerException("Key[] can not be null");
  165.     }
  166.     for (int i = 0; i < keys.length; i++) {
  167.       addFalsePositive(keys[i]);
  168.     }
  169.   }
  170.   /**
  171.    * Performs the selective clearing for a given key.
  172.    * @param k The false positive key to remove from <i>this</i> retouched Bloom filter.
  173.    * @param scheme The selective clearing scheme to apply.
  174.    */
  175.   public void selectiveClearing(Key k, short scheme) {
  176.     if (k == null) {
  177.       throw new NullPointerException("Key can not be null");
  178.     }
  179.     if (!membershipTest(k)) {
  180.       throw new IllegalArgumentException("Key is not a member");
  181.     }
  182.     int index = 0;
  183.     int[] h = hash.hash(k);
  184.     switch(scheme) {
  185.     case RANDOM:
  186.       index = randomRemove();
  187.       break;
  188.     
  189.     case MINIMUM_FN:
  190.       index = minimumFnRemove(h);
  191.       break;
  192.     
  193.     case MAXIMUM_FP:
  194.       index = maximumFpRemove(h);
  195.       break;
  196.     
  197.     case RATIO:
  198.       index = ratioRemove(h);
  199.       break;
  200.     
  201.     default:
  202.       throw new AssertionError("Undefined selective clearing scheme");
  203.     }
  204.     clearBit(index);
  205.   }
  206.   private int randomRemove() {
  207.     if (rand == null) {
  208.       rand = new Random();
  209.     }
  210.     return rand.nextInt(nbHash);
  211.   }
  212.   /**
  213.    * Chooses the bit position that minimizes the number of false negative generated.
  214.    * @param h The different bit positions.
  215.    * @return The position that minimizes the number of false negative generated.
  216.    */
  217.   private int minimumFnRemove(int[] h) {
  218.     int minIndex = Integer.MAX_VALUE;
  219.     double minValue = Double.MAX_VALUE;
  220.     for (int i = 0; i < nbHash; i++) {
  221.       double keyWeight = getWeight(keyVector[h[i]]);
  222.       if (keyWeight < minValue) {
  223.         minIndex = h[i];
  224.         minValue = keyWeight;
  225.       }
  226.     }
  227.     return minIndex;
  228.   }
  229.   /**
  230.    * Chooses the bit position that maximizes the number of false positive removed.
  231.    * @param h The different bit positions.
  232.    * @return The position that maximizes the number of false positive removed.
  233.    */
  234.   private int maximumFpRemove(int[] h) {
  235.     int maxIndex = Integer.MIN_VALUE;
  236.     double maxValue = Double.MIN_VALUE;
  237.     for (int i = 0; i < nbHash; i++) {
  238.       double fpWeight = getWeight(fpVector[h[i]]);
  239.       if (fpWeight > maxValue) {
  240.         maxValue = fpWeight;
  241.         maxIndex = h[i];
  242.       }
  243.     }
  244.     return maxIndex;
  245.   }
  246.   /**
  247.    * Chooses the bit position that minimizes the number of false negative generated while maximizing.
  248.    * the number of false positive removed.
  249.    * @param h The different bit positions.
  250.    * @return The position that minimizes the number of false negative generated while maximizing.
  251.    */
  252.   private int ratioRemove(int[] h) {
  253.     computeRatio();
  254.     int minIndex = Integer.MAX_VALUE;
  255.     double minValue = Double.MAX_VALUE;
  256.     for (int i = 0; i < nbHash; i++) {
  257.       if (ratio[h[i]] < minValue) {
  258.         minValue = ratio[h[i]];
  259.         minIndex = h[i];
  260.       }
  261.     }
  262.     return minIndex;
  263.   }
  264.   /**
  265.    * Clears a specified bit in the bit vector and keeps up-to-date the KeyList vectors.
  266.    * @param index The position of the bit to clear.
  267.    */
  268.   private void clearBit(int index) {
  269.     if (index < 0 || index >= vectorSize) {
  270.       throw new ArrayIndexOutOfBoundsException(index);
  271.     }
  272.     List<Key> kl = keyVector[index];
  273.     List<Key> fpl = fpVector[index];
  274.     // update key list
  275.     int listSize = kl.size();
  276.     for (int i = 0; i < listSize && !kl.isEmpty(); i++) {
  277.       removeKey(kl.get(0), keyVector);
  278.     }
  279.     kl.clear();
  280.     keyVector[index].clear();
  281.     //update false positive list
  282.     listSize = fpl.size();
  283.     for (int i = 0; i < listSize && !fpl.isEmpty(); i++) {
  284.       removeKey(fpl.get(0), fpVector);
  285.     }
  286.     fpl.clear();
  287.     fpVector[index].clear();
  288.     //update ratio
  289.     ratio[index] = 0.0;
  290.     //update bit vector
  291.     bits.clear(index);
  292.   }
  293.   /**
  294.    * Removes a given key from <i>this</i> filer.
  295.    * @param k The key to remove.
  296.    * @param vector The counting vector associated to the key.
  297.    */
  298.   private void removeKey(Key k, List<Key>[] vector) {
  299.     if (k == null) {
  300.       throw new NullPointerException("Key can not be null");
  301.     }
  302.     if (vector == null) {
  303.       throw new NullPointerException("ArrayList<Key>[] can not be null");
  304.     }
  305.     int[] h = hash.hash(k);
  306.     hash.clear();
  307.     for (int i = 0; i < nbHash; i++) {
  308.       vector[h[i]].remove(k);
  309.     }
  310.   }
  311.   /**
  312.    * Computes the ratio A/FP.
  313.    */
  314.   private void computeRatio() {
  315.     for (int i = 0; i < vectorSize; i++) {
  316.       double keyWeight = getWeight(keyVector[i]);
  317.       double fpWeight = getWeight(fpVector[i]);
  318.       if (keyWeight > 0 && fpWeight > 0) {
  319.         ratio[i] = keyWeight / fpWeight;
  320.       }
  321.     }
  322.   }
  323.   private double getWeight(List<Key> keyList) {
  324.     double weight = 0.0;
  325.     for (Key k : keyList) {
  326.       weight += k.getWeight();
  327.     }
  328.     return weight;
  329.   }
  330.   
  331.   /**
  332.    * Creates and initialises the various vectors.
  333.    */
  334.   @SuppressWarnings("unchecked")
  335.   private void createVector() {
  336.     fpVector = new List[vectorSize];
  337.     keyVector = new List[vectorSize];
  338.     ratio = new double[vectorSize];
  339.     for (int i = 0; i < vectorSize; i++) {
  340.       fpVector[i] = Collections.synchronizedList(new ArrayList<Key>());
  341.       keyVector[i] = Collections.synchronizedList(new ArrayList<Key>());
  342.       ratio[i] = 0.0;
  343.     }
  344.   }
  345.   
  346.   // Writable
  347.   @Override
  348.   public void write(DataOutput out) throws IOException {
  349.     super.write(out);
  350.     for (int i = 0; i < fpVector.length; i++) {
  351.       List<Key> list = fpVector[i];
  352.       out.writeInt(list.size());
  353.       for (Key k : list) {
  354.         k.write(out);
  355.       }
  356.     }
  357.     for (int i = 0; i < keyVector.length; i++) {
  358.       List<Key> list = keyVector[i];
  359.       out.writeInt(list.size());
  360.       for (Key k : list) {
  361.         k.write(out);
  362.       }
  363.     }
  364.     for (int i = 0; i < ratio.length; i++) {
  365.       out.writeDouble(ratio[i]);
  366.     }
  367.   }
  368.   @Override
  369.   public void readFields(DataInput in) throws IOException {
  370.     super.readFields(in);
  371.     createVector();
  372.     for (int i = 0; i < fpVector.length; i++) {
  373.       List<Key> list = fpVector[i];
  374.       int size = in.readInt();
  375.       for (int j = 0; j < size; j++) {
  376.         Key k = new Key();
  377.         k.readFields(in);
  378.         list.add(k);
  379.       }
  380.     }
  381.     for (int i = 0; i < keyVector.length; i++) {
  382.       List<Key> list = keyVector[i];
  383.       int size = in.readInt();
  384.       for (int j = 0; j < size; j++) {
  385.         Key k = new Key();
  386.         k.readFields(in);
  387.         list.add(k);
  388.       }
  389.     }
  390.     for (int i = 0; i < ratio.length; i++) {
  391.       ratio[i] = in.readDouble();
  392.     }
  393.   }
  394. }