Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Approximate counting in Java #898

Merged
merged 11 commits into from
Dec 2, 2021
2 changes: 2 additions & 0 deletions contents/approximate_counting/approximate_counting.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ As we do not have any objects to count, we will instead simulate the counting wi
[import, lang:"cpp"](code/c++/approximate_counting.cpp)
{% sample lang="python" %}
[import, lang:"python"](code/python/approximate_counting.py)
{% sample lang="java" %}
[import, lang:"java"](code/java/ApproximateCounting.java)
{% endmethod %}

### Bibliography
Expand Down
84 changes: 84 additions & 0 deletions contents/approximate_counting/code/java/ApproximateCounting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import java.lang.Math;
import java.util.stream.DoubleStream;

public class ApproximateCounting {

/*
* This function taks
* - v: value in register
* - a: a scaling value for the logarithm based on Morris's paper
* It returns the approximate count
*/
static double n(double v, double a) {
return a * (Math.pow(1 + 1 / a, v) - 1);
}


/*
* This function takes
* - v: value in register
* - a: a scaling value for the logarithm based on Morris's paper
* It returns the new value for v
*/
static double increment(double v, double a) {
double delta = 1 / (n(v + 1, a) - n(v, a));

if (Math.random() <= delta) {
return v + 1;
} else {
return v;
}
}



/*
* This function takes
* - v: value in register
* - a: a scaling value for the logarithm based on Morris's paper
* It returns the new value for v
*/
static double approximateCount(int nItems, double a) {
double v = 0;

for (int i = 0; i < nItems; i++) {
v = increment(v, a);
}

return n(v, a);
}

/*
* This function takes
* - nTrials: the number of counting trails
* - nItems: the number of items to count
* - a: a scaling value for the logarithm based on Morris's paper
* - threshold: the maximum percent error allowed
* It terminates the program on failure
*/
static void testApproximateCount(int nTrials, int nItems, double a, double threshold) {
double avg = DoubleStream.generate(() -> approximateCount(nItems, a))
.limit(nTrials)
.average()
.getAsDouble();

if (Math.abs((avg - nItems) / nItems) < threshold) {
System.out.println("passed");
} else {
System.out.println("failed");
}
}


public static void main(String args[]) {
System.out.println("testing 1,000, a = 30, 10% error");
testApproximateCount(100, 1_000, 30, 0.1);

System.out.println("testing 12,345, a = 10, 10% error");
testApproximateCount(100, 12_345, 10, 0.1);

System.out.println("testing 222,222, a = 0.5, 20% error");
testApproximateCount(100, 222_222, 0.5, 0.2);
}

}