glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / set / ibf_sim.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2013 GNUnet e.V.
4
5       GNUnet is free software: you can redistribute it and/or modify it
6       under the terms of the GNU Affero General Public License as published
7       by the Free Software Foundation, either version 3 of the License,
8       or (at your option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       Affero General Public License for more details.
14 */
15
16 /**
17  * @file set/ibf_sim.c
18  * @brief implementation of simulation for invertible bloom filter
19  * @author Florian Dold
20  *
21  * This code was used for some internal experiments, it is not
22  * build or shipped as part of the GNUnet system.
23  */
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #define MAX_IBF_DECODE 16
29
30 /* report average over how many rounds? */
31 #define ROUNDS 100000
32
33 /* enable one of the three below */
34 // simple fix
35 #define FIX1 0
36 // possibly slightly better fix for large IBF_DECODE values
37 #define FIX2 1
38
39 // SIGCOMM algorithm
40 #define STRATA 0
41
42 // print each value?
43 #define VERBOSE 0
44 // avoid assembly? (ASM is about 50% faster)
45 #define SLOW 0
46
47 int
48 main(int argc, char **argv)
49 {
50   unsigned int round;
51   unsigned int buckets[31]; // max is 2^31 as 'random' returns only between 0 and 2^31
52   unsigned int i;
53   int j;
54   unsigned int r;
55   unsigned int ret;
56   unsigned long long total;
57   unsigned int want;
58   double predict;
59
60   srandom (time (NULL));
61   total = 0;
62   want = atoi (argv[1]);
63   for (round=0;round<ROUNDS;round++)
64   {
65     memset (buckets, 0, sizeof (buckets));
66     for (i=0;i<want;i++)
67     {
68       /* FIXME: might want to use 'better' PRNG to avoid
69          PRNG-induced biases */
70       r = random ();
71       if (0 == r)
72         continue;
73 #if SLOW
74       for (j=0;(j < 31) && (0 == (r & (1 << j)));j++) ;
75 #else
76       /* use assembly / gcc */
77       j = __builtin_ffs (r) - 1;
78 #endif
79       buckets[j]++;
80     }
81     ret = 0;
82     predict = 0.0;
83     for (j=31;j >= 0; j--)
84     {
85 #if FIX1
86       /* improved algorithm, for 1000 elements with IBF-DECODE 8, I
87          get 990/1000 elements on average over 1 million runs; key
88          idea being to stop short of the 'last' possible IBF as
89          otherwise a "lowball" per-chance would unduely influence the
90          result */
91       if ( (j > 0) &&
92            (buckets[j - 1] > MAX_IBF_DECODE) )
93       {
94         ret *= (1 << (j + 1));
95         break;
96       }
97 #endif
98 #if FIX2
99       /* another improvement: don't just always cut off the last one,
100          but rather try to predict based on all previous values where
101          that "last" one is; additional prediction can only really
102          work if MAX_IBF_DECODE is sufficiently high */
103       if (  (j > 0) &&
104             ( (buckets[j - 1] > MAX_IBF_DECODE) ||
105               (predict > MAX_IBF_DECODE) ) )
106       {
107         ret *= (1 << (j + 1));
108         break;
109       }
110 #endif
111 #if STRATA
112       /* original algorithm, for 1000 elements with IBF-DECODE 8,
113          I get 920/1000 elements on average over 1 million runs */
114       if (buckets[j] > MAX_IBF_DECODE)
115         {
116           ret *= (1 << (j+1));
117           break;
118         }
119 #endif
120       ret += buckets[j];
121       predict = (buckets[j] + 2.0 * predict) / 2.0;
122     }
123 #if VERBOSE
124     fprintf (stderr, "%u ", ret);
125 #endif
126     total += ret;
127   }
128   fprintf (stderr, "\n");
129   fprintf (stdout, "average %llu\n", total / ROUNDS);
130   return 0;
131 }
132
133 /* TODO: should calculate stddev of the results to also be able to
134    say something about the stability of the results, outside of
135    large-scale averages -- gaining 8% precision at the expense of
136    50% additional variance might not be worth it... */