2 * libsortnetwork - src/sn-count-cuts.c
3 * Copyright (C) 2008-2011 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Florian octo Forster <ff at octo.it>
32 #include "sn_network.h"
33 #include "sn_random.h"
34 #include "sn_hashtable.h"
36 static int cuts_num = 0;
37 static uint64_t iterations_num = 1000000;
38 static char *input_file = NULL;
40 static sn_hashtable_t *hashtable;
42 static double possible_cuts (int inputs_num) /* {{{ */
44 double n = (double) inputs_num;
45 double k = (double) cuts_num;
47 double tmp = lgamma (1.0 + n)
48 - (lgamma (1.0 + k) + lgamma (1.0 + n - k));
50 return (pow (2.0, k) * exp (tmp));
51 } /* }}} double possible_cuts */
53 static double estimate_reachable_networks (sn_network_t *n) /* {{{ */
55 double cuts = possible_cuts (SN_NETWORK_INPUT_NUM (n));
56 double pct = sn_hashtable_get_networks_pct (hashtable) / 100.0;
59 } /* }}} double estimate_reachable_networks */
61 static void exit_usage (void) /* {{{ */
63 printf ("sn-count-cuts [options] <file0> <file1>\n"
66 " -c Number of cuts to perform.\n"
67 " -n Maximum number of cuts to perform.\n"
68 " -h Display this help and exit.\n"
71 } /* }}} void exit_usage */
73 static int read_options (int argc, char **argv) /* {{{ */
77 while ((option = getopt (argc, argv, "c:n:h")) != -1)
83 int tmp = atoi (optarg);
86 fprintf (stderr, "Not a valid number of cuts: %s\n", optarg);
95 uint64_t tmp = (uint64_t) strtoull (optarg, /* endptr = */ NULL, /* base = */ 10);
98 fprintf (stderr, "Not a valid number of iterations: %s\n", optarg);
101 iterations_num = tmp;
111 if ((argc - optind) >= 1)
112 input_file = argv[optind];
115 } /* }}} int read_options */
117 static int create_random_cut (const sn_network_t *n) /* {{{ */
119 sn_network_t *n_copy;
120 int mask[SN_NETWORK_INPUT_NUM (n)];
121 int cuts_left = cuts_num;
124 memset (mask, 0, sizeof (mask));
125 while (cuts_left > 0)
127 int input = sn_bounded_random (0, SN_NETWORK_INPUT_NUM (n));
129 if (mask[input] != 0)
132 mask[input] = (2 * sn_bounded_random (0, 1)) - 1;
136 n_copy = sn_network_clone (n);
140 status = sn_network_cut (n_copy, mask);
143 sn_network_destroy (n_copy);
147 sn_network_unify (n_copy);
149 sn_hashtable_account (hashtable, n_copy);
151 sn_network_destroy (n_copy);
153 } /* }}} int create_random_cut */
155 static int print_stats (sn_network_t *n) /* {{{ */
157 static _Bool first_call = 1;
161 printf ("# iterations unique collisions estimate\n");
165 printf ("%"PRIu64" %"PRIu64" %"PRIu64" %.0f\n",
166 sn_hashtable_get_total (hashtable),
167 sn_hashtable_get_networks (hashtable),
168 sn_hashtable_get_collisions (hashtable),
169 estimate_reachable_networks (n));
172 } /* }}} int print_stats */
174 int main (int argc, char **argv) /* {{{ */
179 read_options (argc, argv);
181 if ((input_file == NULL)
182 || (strcmp ("-", input_file) == 0))
183 n = sn_network_read (stdin);
185 n = sn_network_read_file (input_file);
188 fprintf (stderr, "Unable to read network.\n");
193 cuts_num = SN_NETWORK_INPUT_NUM (n) / 2;
195 hashtable = sn_hashtable_create ();
196 if (hashtable == NULL)
199 for (i = 0; i < iterations_num; i++)
201 create_random_cut (n);
204 || ((i < 1000) && (((i + 1) % 10) == 0))
205 || ((i < 10000) && (((i + 1) % 100) == 0))
206 || ((i < 100000) && (((i + 1) % 1000) == 0))
207 || ((i < 1000000) && (((i + 1) % 10000) == 0))
208 || ((i < 10000000) && (((i + 1) % 100000) == 0)))
213 || (((i - 1) < 1000) && ((i % 10) == 0))
214 || (((i - 1) < 10000) && ((i % 100) == 0))
215 || (((i - 1) < 100000) && ((i % 1000) == 0))
216 || (((i - 1) < 1000000) && ((i % 10000) == 0))
217 || (((i - 1) < 10000000) && ((i % 100000) == 0)))
229 /* vim: set shiftwidth=2 softtabstop=2 fdm=marker : */