From 32164fc1e00e7658415bc9595205812794d8a0c4 Mon Sep 17 00:00:00 2001 From: Mahdi Sarikhani Date: Mon, 23 Aug 2021 23:26:20 +0430 Subject: [PATCH 1/2] Add approximate counting algorithm in C --- .../approximate_counting.md | 2 + .../code/c/approximate_counting.c | 82 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 contents/approximate_counting/code/c/approximate_counting.c diff --git a/contents/approximate_counting/approximate_counting.md b/contents/approximate_counting/approximate_counting.md index d254b99a2..fe148dcf7 100644 --- a/contents/approximate_counting/approximate_counting.md +++ b/contents/approximate_counting/approximate_counting.md @@ -360,6 +360,8 @@ As we do not have any objects to count, we will instead simulate the counting wi {% method %} {% sample lang="jl" %} [import, lang:"julia"](code/julia/approximate_counting.jl) +{% sample lang="c" %} +[import, lang:"c"](code/c/approximate_counting.c) {% endmethod %} ### Bibliography diff --git a/contents/approximate_counting/code/c/approximate_counting.c b/contents/approximate_counting/code/c/approximate_counting.c new file mode 100644 index 000000000..f6aff0d3d --- /dev/null +++ b/contents/approximate_counting/code/c/approximate_counting.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +// This function returns a pseudo-random number between 0 and 1 +double drand() +{ + return (double)rand() / RAND_MAX; +} + +// This function takes +// - v: value in register +// - a: a scaling value for the logarithm based on Morris's paper +// It returns the approximate count +double n(double v, double a) +{ + return a * (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 a new value for v +double increment(double v, double a) +{ + // delta is the probability of incrementing our counter + double delta = 1 / (n(v + 1, a) - n(v, a)); + + if (drand() <= delta) { + return v + 1; + } + return v; +} + +// This function simulates counting and takes +// - n_items: number of items to count and loop over +// - a: a scaling value for the logarithm based on Morris's paper +// It returns n(v, a), the approximate count +double approximate_count(size_t n_items, double a) +{ + int v = 0; + for (size_t i = 0; i < n_items; ++i) { + v = increment(v, a); + } + + return n(v, a); +} + +// This function takes +// - n_trials: the number of counting trials +// - n_items: the number off 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 +void test_approximation_count(size_t n_trials, size_t n_items, double a, + double threshold) +{ + double sum = 0.0; + for (size_t i = 0; i < n_trials; ++i) { + sum += approximate_count(n_items, a); + } + double avg = sum / n_trials; + + assert(fabs((avg - n_items) / n_items) < threshold); +} + +int main() +{ + srand(time(NULL)); + + printf("Counting Tests, 100 trials\n"); + printf("testing 1000, a = 30, 1%% error\n"); + test_approximation_count(100, 1000, 30, 0.1); + printf("testing 12345, a = 10, 1%% error\n"); + test_approximation_count(100, 12345, 10, 0.1); + printf("testing 222222, a = 0.5, 10%% error\n"); + test_approximation_count(100, 222222, 0.5, 0.1); + + return 0; +} From 256bf77aead230be8f72ff40faea8a03273ea05b Mon Sep 17 00:00:00 2001 From: Mahdi Sarikhani <24981501+mahdisarikhani@users.noreply.github.com> Date: Thu, 26 Aug 2021 04:11:16 +0430 Subject: [PATCH 2/2] Fix typo Co-authored-by: stormofice <58337328+stormofice@users.noreply.github.com> --- contents/approximate_counting/code/c/approximate_counting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/approximate_counting/code/c/approximate_counting.c b/contents/approximate_counting/code/c/approximate_counting.c index f6aff0d3d..ded7a518e 100644 --- a/contents/approximate_counting/code/c/approximate_counting.c +++ b/contents/approximate_counting/code/c/approximate_counting.c @@ -76,7 +76,7 @@ int main() printf("testing 12345, a = 10, 1%% error\n"); test_approximation_count(100, 12345, 10, 0.1); printf("testing 222222, a = 0.5, 10%% error\n"); - test_approximation_count(100, 222222, 0.5, 0.1); + test_approximation_count(100, 222222, 0.5, 0.2); return 0; }