Skip to content

Add Approximate counting in Java #898

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

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
82 changes: 82 additions & 0 deletions contents/approximate_counting/code/java/ApproximateCounting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
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 = 1; i < nItems + 1; i++) {
v = increment(v, a);
}

return n(v, a);
}

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

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it terminate the program on failure? You don't seem to check anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure. I don't think this function should terminate the program on failure.
As I understand this function, it should only print whether the calculation was successful or not. However, I can add the else part to the if expression to print "failed" if the test has failed.



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

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

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

}