package net.varkhan.base.containers.set; import net.varkhan.base.containers.Hashes; import net.varkhan.base.containers.HashingStrategy; import net.varkhan.base.containers.Iterator; import net.varkhan.base.containers.array.BitArrays; import java.io.Serializable; /** * <b></b>. * <p/> * * @author varkhan * @date 2/11/12 * @time 3:45 PM */ public class BloomWeightingSet<Key> implements WeightingSet<Key>, Serializable, Cloneable { protected final HashingStrategy<Key> hash; protected long size =0; protected double weight=0; protected final int num; protected final int len; protected final long msk; protected /*final*/ float[] filter; @SuppressWarnings("unchecked") public BloomWeightingSet(int num, int len) { this((HashingStrategy<Key>) Hashes.DefaultHashingStrategy, num, len); } public BloomWeightingSet(HashingStrategy<Key> hash, int num, int len) { this.hash=hash; this.num=num>512 ? 512 : num; this.len=(1<<BitArrays.lsb(len)); this.msk=(1<<BitArrays.lsb(len))-1; this.filter = new float[this.len]; } protected int hash(long h, int i) { return (int) (Hashes.mix(h+i) & msk); } public long size() { return size; } public boolean isEmpty() { return weight==0; } public double weight() { return weight; } public void clear() { size = 0; weight= 0; for(int i=0; i<filter.length; i++) filter[i] = 0; } public boolean add(Key key) { return add(key,1.0); } public boolean add(Key key, double wgh) { if(wgh==0) return false; long h = hash.hash(key); boolean a = false; boolean d = false; for(int i=0; i<num; i++) { int p = hash(h, i); if(filter[p]==0) a = true; if((filter[p] += wgh)==0) d = true; } if(a) size++; if(d) size--; weight += wgh; return a||d; } public boolean del(Key key) { long h = hash.hash(key); float wp = +Float.MAX_VALUE; float wm = -Float.MAX_VALUE; for(int i=0; i<num; i++) { int p = hash(h, i); float x = filter[p]; if(wp>x && x>0) wp=x; if(wm<x && x<0) wm=x; } if(wp==0||wm==0) return false; float w = (wp>-wm)?wm:wp; for(int i=0; i<num; i++) { int p = hash(h, i); filter[p]-=w; } size--; weight -= w; return true; } public boolean has(Key key) { long h = hash.hash(key); for(int i=0; i<num; i++) { int p = hash(h, i); float x = filter[p]; if(x==0) return false; } return true; } public double weight(Key key) { long h = hash.hash(key); float wp = +Float.MAX_VALUE; float wm = -Float.MAX_VALUE; for(int i=0; i<num; i++) { int p = hash(h, i); float x = filter[p]; if(wp>x && x>0) wp=x; if(wm<x && x<0) wm=x; } if(wp>-wm) return wm; else return wp; } @SuppressWarnings({ "unchecked" }) public Iterator<? extends Key> iterator() { return Iterator.EMPTY; } public <Par> long visit(Visitor<Key,Par> vis, Par par) { return 0; } public String toString() { StringBuilder buf = new StringBuilder(); for(int i=0; i<this.filter.length; i++) { if(i>0) buf.append('|'); buf.append(filter[i]>0 ? String.format("%3f", filter[i]) : " "); } return buf.toString(); } @SuppressWarnings("unchecked") public BloomWeightingSet<Key> clone() { BloomWeightingSet<Key> c; try { c=(BloomWeightingSet<Key>) super.clone(); } catch(CloneNotSupportedException e) { throw new InternalError(); } c.filter = this.filter.clone(); return c; } }