Advertisement
IEclipseI

unique

May 24th, 2019
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.87 KB | None | 0 0
  1. #include <set>
  2. #include <random>
  3. #include <cassert>
  4. #include <iostream>
  5. #include <algorithm>
  6.  
  7. class UniqCounter {
  8. private:
  9.     static constexpr size_t p = 11u;
  10.     static constexpr size_t m = 1u << p;
  11.     static constexpr size_t shift = 32u - p;
  12.     static constexpr double alpha = 0.7213 / (1 + 1.079 / m);
  13.     static constexpr size_t sel = 1u << (14u - p);
  14.     uint32_t M[sel][m];
  15. public:
  16.     UniqCounter() {
  17.         for (size_t i = 0; i < sel; ++i) {
  18.             for (size_t j = 0; j < m; j++) {
  19.                 M[i][j] = 0;
  20.             }
  21.         }
  22.     }
  23.  
  24. public:
  25.     void add(int x) {
  26.         uint32_t value = x;
  27.         for (size_t i = 0; i < sel; ++i) {
  28.             value = hash(value);
  29.             uint32_t prefix = value >> shift;
  30.             M[i][prefix] = std::max(M[i][prefix], rank(value));
  31.         }
  32.     }
  33.  
  34.     int get_uniq_num() const {
  35.         std::vector<double> ar(sel);
  36.         for (size_t i = 0; i < sel; ++i) {
  37.             double sum = 0;
  38.             for (size_t j = 0; j < m; ++j) {
  39.                 sum += 1 / pow(2, M[i][j]);
  40.             }
  41.             double E = alpha * m * m / sum;
  42.             if (E <= 2.5 * m) {
  43.                 size_t V = 0;
  44.                 for (size_t j = 0; j < m; ++j) {
  45.                     if (M[i][j] == 0)
  46.                         V++;
  47.                 }
  48.                 if (V != 0) {
  49.                     E = m * log(m / (double) V);
  50.                 }
  51.             }
  52.             ar[i] = E;
  53.         }
  54.         double E = 0;
  55.         std::sort(ar.begin(), ar.end());
  56.         for (size_t i = sel / 4u;
  57.              i < 3u * sel / 4u; ++i) { //if selections count divide by 4, everything is ok here
  58.             E += ar[i];
  59.         }
  60.         return E / (sel / 2u);
  61.     }
  62.  
  63. private:
  64.     uint32_t rank(uint32_t x) {
  65.         uint32_t r = 1;
  66.         while ((x & 1u) == 0 && r <= 32u - p) {
  67.             ++r;
  68.             x >>= 1u;
  69.         }
  70.         return r;
  71.     }
  72.  
  73.     uint32_t hash(uint32_t x) {
  74.         x = ((x >> 16) ^ x) * 0x119de1f3;
  75.         x = ((x >> 16) ^ x) * 0x119de1f3;
  76.         x = ((x >> 16) ^ x) * 0x119de1f3;
  77.         x = ((x >> 16) ^ x) * 0x119de1f3;
  78.         x = (x >> 16) ^ x;
  79.         return x;
  80.     }
  81. };
  82.  
  83. double relative_error(int expected, int got) {
  84.     return abs(got - expected) / (double) expected;
  85. }
  86.  
  87. void BLOCK(const std::string &block_name) {
  88.     std::cout << "BLOCK: " << block_name << ": " << std::endl;
  89. }
  90.  
  91.  
  92. int main() {
  93.     {
  94.         std::random_device rd;
  95.         std::mt19937 gen(rd());
  96.         const int N = (int) 1e6;
  97.         for (int k : {1, 10, 1000, 10000, N / 10, N, N * 10}) {
  98.             std::uniform_int_distribution<> dis(1, k);
  99.             std::set<int> all;
  100.             UniqCounter counter;
  101.             for (int i = 0; i < N; i++) {
  102.                 int value = dis(gen);
  103.                 all.insert(value);
  104.                 counter.add(value);
  105.             }
  106.             int expected = (int) all.size();
  107.             int counter_result = counter.get_uniq_num();
  108.             double error = relative_error(expected, counter_result);
  109.             printf("%d numbers in range [1 .. %d], %d uniq, %d result, %.5f relative error\n", N, k, expected,
  110.                    counter_result, error);
  111.             assert(error <= 0.1);
  112.         }
  113.     }
  114.  
  115.     {
  116.         BLOCK("Just random numbers");
  117.         std::random_device rd;
  118.         const int N = (int) 1e6;
  119.         for (int i = 0; i < 4; ++i) {
  120.             std::set<int> all;
  121.             UniqCounter counter;
  122.             for (int j = 0; j < N; j++) {
  123.                 int value = rd();
  124.                 all.insert(value);
  125.                 counter.add(value);
  126.             }
  127.             int expected = (int) all.size();
  128.             int counter_result = counter.get_uniq_num();
  129.             double error = relative_error(expected, counter_result);
  130.             printf("%d numbers in range [%d .. %d], %d uniq, %d result, %.5f relative error\n", N,
  131.                    std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), expected,
  132.                    counter_result, error);
  133.             assert(error <= 0.1);
  134.         }
  135.     }
  136.  
  137.  
  138.     {
  139.         //it is so long test
  140.         BLOCK("Many insertions");
  141.         std::random_device rd;
  142.         const int N = std::numeric_limits<int>::max();
  143.         UniqCounter counter;
  144.         for (int i = 0; i < N; i++) {
  145. //            if (i % (int) 1e7 == 0) //to see progress
  146. //                std::cout << i / 1e7 << std::endl;
  147.             counter.add(rd());
  148.         }
  149.         int expected = N;
  150.         int counter_result = counter.get_uniq_num();
  151.         double error = relative_error(expected, counter_result);
  152.         printf("%d numbers in range [%d .. %d], ~%d uniq, %d result, %.5f relative error\n", N,
  153.                std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), expected,
  154.                counter_result, error);
  155.         assert(error <= 0.1);
  156.     }
  157.  
  158.     return 0;
  159. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement