package org.streaminer.stream.change; import java.util.ArrayList; import java.util.List; import org.apache.mahout.math.Arrays; import org.streaminer.util.hash.HashUtils; /** * * @author Maycon Viana Bordin <mayconbordin@gmail.com> */ public class AbsoluteChange extends AbstractChange { private int[][] counts; public AbsoluteChange(int width, int depth, int lgn) { super(width, depth, lgn); counts = new int[size][lgn+1]; } /** * Update the count of an item. * @param item The idenfitier of the item being updated * @param diff The change, positive or negative */ public void add(long item, int diff) { long hash; // for each set of groups, find the group that the item belongs in, update it for (int i=0; i<depth; i++) { // use the hash function to find the place where the item belongs hash = HashUtils.hash31(testa[i], testb[i], item); hash = hash % width; // call external routine to update the counts logInsert(counts[i * width + (int)hash], (int)item, lgn, diff); } } public List<Long> getDeltoids(int thresh) { long guess, hash; int testval = 0; List<Long> results = new ArrayList<Long>(); for (int i=0; i<depth; i++) { for (int j=0; j<width; j++) { // go over all the different tests and see if there is a // deltoid within each test guess = findOne(testval, thresh); if (guess > 0) { hash = HashUtils.hash31(testa[i], testb[i], guess); hash = hash % width; // check item does hash into that bucket... if (hash == j) { if (!results.contains(guess)) results.add(guess); } } // advance to next item testval++; } } return results; } /** * Search through a set of tests to detect whether there is a deltoid there * returns 0 if none found, returns id of found item otherwise. * @param thresh * @return */ private long findOne(int pos, int thresh) { long j = 1, k = 0; if (Math.abs(counts[pos][0]) < thresh) { k = 0; } else { int c = counts[pos][0]; for (int i=lgn; i>0; i--) { // main test: if one side is above threshold and the otherside is not if (isOneSideAbove(counts[pos][i], (c - counts[pos][i]), thresh)) { k = 0; // if test fails, bail out break; } if (Math.abs(counts[pos][i]) >= thresh) k += j; // build the binary representation of the item j = j << 1; } } return k; } private boolean isOneSideAbove(int a, int b, int thresh) { return ((Math.abs(a) < thresh && Math.abs(b) < thresh) || (Math.abs(a) >= thresh && Math.abs(b) >= thresh)); } }