stable version
This commit is contained in:
parent
1cfaf691bd
commit
69c177a494
245
src/bmz.c
245
src/bmz.c
@ -22,8 +22,9 @@ static const char bitmask[8] = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 <<
|
|||||||
#define UNSETBIT(array, i) (array[(i) / 8] &= (~(bitmask[(i) % 8])))
|
#define UNSETBIT(array, i) (array[(i) / 8] &= (~(bitmask[(i) % 8])))
|
||||||
|
|
||||||
static int bmz_gen_edges(mph_t *mph);
|
static int bmz_gen_edges(mph_t *mph);
|
||||||
static void bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 * biggest_g_value, uint32 * biggest_edge_value, uint8 * used_edges);
|
static uint8 bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 * biggest_g_value, uint32 * biggest_edge_value, uint8 * used_edges, uint8 * visited);
|
||||||
static void bmz_traverse_non_critical_nodes(bmz_mph_data_t *bmz, uint8 * used_edges);
|
static uint8 bmz_traverse_critical_nodes_heuristic(bmz_mph_data_t *bmz, uint32 v, uint32 * biggest_g_value, uint32 * biggest_edge_value, uint8 * used_edges, uint8 * visited);
|
||||||
|
static void bmz_traverse_non_critical_nodes(bmz_mph_data_t *bmz, uint8 * used_edges, uint8 * visited);
|
||||||
|
|
||||||
|
|
||||||
mph_t *bmz_mph_new(key_source_t *key_source)
|
mph_t *bmz_mph_new(key_source_t *key_source)
|
||||||
@ -72,12 +73,13 @@ mphf_t *bmz_mph_create(mph_t *mph, float bmz_c)
|
|||||||
{
|
{
|
||||||
mphf_t *mphf = NULL;
|
mphf_t *mphf = NULL;
|
||||||
bmz_mphf_data_t *bmzf = NULL;
|
bmz_mphf_data_t *bmzf = NULL;
|
||||||
|
|
||||||
uint32 i;
|
uint32 i;
|
||||||
uint32 iterations = 10;
|
uint32 iterations;
|
||||||
|
uint32 iterations_map = 20;
|
||||||
uint8 *used_edges = NULL;
|
uint8 *used_edges = NULL;
|
||||||
uint32 biggest_g_value = 0;
|
uint8 restart_mapping = 0;
|
||||||
uint32 biggest_edge_value = 1;
|
uint8 * visited = NULL;
|
||||||
|
|
||||||
DEBUGP("bmz_c: %f\n", bmz_c);
|
DEBUGP("bmz_c: %f\n", bmz_c);
|
||||||
bmz_mph_data_t *bmz = (bmz_mph_data_t *)mph->data;
|
bmz_mph_data_t *bmz = (bmz_mph_data_t *)mph->data;
|
||||||
bmz->m = mph->key_source->nkeys;
|
bmz->m = mph->key_source->nkeys;
|
||||||
@ -89,13 +91,18 @@ mphf_t *bmz_mph_create(mph_t *mph, float bmz_c)
|
|||||||
bmz->hashes = (hash_state_t **)malloc(sizeof(hash_state_t *)*3);
|
bmz->hashes = (hash_state_t **)malloc(sizeof(hash_state_t *)*3);
|
||||||
for(i = 0; i < 3; ++i) bmz->hashes[i] = NULL;
|
for(i = 0; i < 3; ++i) bmz->hashes[i] = NULL;
|
||||||
|
|
||||||
// Mapping step
|
do
|
||||||
if (mph->verbosity)
|
|
||||||
{
|
{
|
||||||
|
// Mapping step
|
||||||
|
uint32 biggest_g_value = 0;
|
||||||
|
uint32 biggest_edge_value = 1;
|
||||||
|
iterations = 20;
|
||||||
|
if (mph->verbosity)
|
||||||
|
{
|
||||||
fprintf(stderr, "Entering mapping step for mph creation of %u keys with graph sized %u\n", bmz->m, bmz->n);
|
fprintf(stderr, "Entering mapping step for mph creation of %u keys with graph sized %u\n", bmz->m, bmz->n);
|
||||||
}
|
}
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
int ok;
|
int ok;
|
||||||
DEBUGP("hash function 1\n");
|
DEBUGP("hash function 1\n");
|
||||||
bmz->hashes[0] = hash_state_new(bmz->hashfuncs[0], bmz->n);
|
bmz->hashes[0] = hash_state_new(bmz->hashfuncs[0], bmz->n);
|
||||||
@ -118,53 +125,63 @@ mphf_t *bmz_mph_create(mph_t *mph, float bmz_c)
|
|||||||
if (iterations == 0) break;
|
if (iterations == 0) break;
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
if (iterations == 0)
|
if (iterations == 0)
|
||||||
{
|
{
|
||||||
graph_destroy(bmz->graph);
|
graph_destroy(bmz->graph);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ordering step
|
// Ordering step
|
||||||
if (mph->verbosity)
|
if (mph->verbosity)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Starting ordering step\n");
|
fprintf(stderr, "Starting ordering step\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
graph_obtain_critical_nodes(bmz->graph);
|
graph_obtain_critical_nodes(bmz->graph);
|
||||||
|
|
||||||
// Searching step
|
// Searching step
|
||||||
if (mph->verbosity)
|
if (mph->verbosity)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Starting Searching step.\n");
|
fprintf(stderr, "Starting Searching step.\n");
|
||||||
fprintf(stderr, "\tTraversing critical vertices.\n");
|
fprintf(stderr, "\tTraversing critical vertices.\n");
|
||||||
}
|
}
|
||||||
DEBUGP("Searching step\n");
|
DEBUGP("Searching step\n");
|
||||||
|
visited = (char *)malloc(bmz->n/8 + 1);
|
||||||
used_edges = (uint8 *)malloc((bmz->m*sizeof(uint8))/8 + 1);
|
memset(visited, 0, bmz->n/8 + 1);
|
||||||
memset(used_edges, 0, bmz->m/8 + 1);
|
used_edges = (uint8 *)malloc(bmz->m/8 + 1);
|
||||||
free(bmz->g);
|
memset(used_edges, 0, bmz->m/8 + 1);
|
||||||
bmz->g = malloc(bmz->n * sizeof(uint32));
|
free(bmz->g);
|
||||||
assert(bmz->g);
|
bmz->g = malloc(bmz->n * sizeof(uint32));
|
||||||
for (i = 0; i < bmz->n; ++i) bmz->g[i] = UNDEFINED;
|
assert(bmz->g);
|
||||||
|
for (i = 0; i < bmz->n; ++i) // critical nodes
|
||||||
for (i = 0; i < bmz->n; ++i) // critical nodes
|
{
|
||||||
{
|
if (graph_node_is_critical(bmz->graph, i) && (!GETBIT(visited,i)))
|
||||||
if (graph_node_is_critical(bmz->graph, i) && (bmz->g[i] == UNDEFINED))
|
|
||||||
{
|
{
|
||||||
bmz_traverse_critical_nodes(bmz, i, &biggest_g_value, &biggest_edge_value, used_edges);
|
if(bmz_c > 1.14) restart_mapping = bmz_traverse_critical_nodes(bmz, i, &biggest_g_value, &biggest_edge_value, used_edges, visited);
|
||||||
|
else restart_mapping = bmz_traverse_critical_nodes_heuristic(bmz, i, &biggest_g_value, &biggest_edge_value, used_edges, visited);
|
||||||
|
if(restart_mapping) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mph->verbosity)
|
if(!restart_mapping)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\tTraversing non critical vertices.\n");
|
if (mph->verbosity)
|
||||||
}
|
{
|
||||||
|
fprintf(stderr, "\tTraversing non critical vertices.\n");
|
||||||
bmz_traverse_non_critical_nodes(bmz, used_edges); // non_critical_nodes
|
}
|
||||||
|
bmz_traverse_non_critical_nodes(bmz, used_edges, visited); // non_critical_nodes
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iterations_map--;
|
||||||
|
if (mph->verbosity) fprintf(stderr, "Restarting mapping step. %u iterations remaining.\n", iterations_map);
|
||||||
|
}
|
||||||
|
free(used_edges);
|
||||||
|
free(visited);
|
||||||
|
}while(restart_mapping && iterations_map > 0);
|
||||||
graph_destroy(bmz->graph);
|
graph_destroy(bmz->graph);
|
||||||
free(used_edges);
|
|
||||||
bmz->graph = NULL;
|
bmz->graph = NULL;
|
||||||
|
if (iterations_map == 0) return NULL;
|
||||||
mphf = (mphf_t *)malloc(sizeof(mphf_t));
|
mphf = (mphf_t *)malloc(sizeof(mphf_t));
|
||||||
mphf->algo = mph->algo;
|
mphf->algo = mph->algo;
|
||||||
bmzf = (bmz_mphf_data_t *)malloc(sizeof(bmz_mph_data_t));
|
bmzf = (bmz_mphf_data_t *)malloc(sizeof(bmz_mph_data_t));
|
||||||
@ -184,19 +201,19 @@ mphf_t *bmz_mph_create(mph_t *mph, float bmz_c)
|
|||||||
return mphf;
|
return mphf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 * biggest_g_value, uint32 * biggest_edge_value, uint8 * used_edges)
|
static uint8 bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 * biggest_g_value, uint32 * biggest_edge_value, uint8 * used_edges, uint8 * visited)
|
||||||
{
|
{
|
||||||
uint32 next_g;
|
uint32 next_g;
|
||||||
uint32 u; /* Auxiliary vertex */
|
uint32 u; /* Auxiliary vertex */
|
||||||
uint32 lav; /* lookahead vertex */
|
uint32 lav; /* lookahead vertex */
|
||||||
uint8 collision;
|
uint8 collision;
|
||||||
vqueue_t * q = vqueue_new((uint32)(0.5*graph_ncritical_nodes(bmz->graph)));
|
vqueue_t * q = vqueue_new((uint32)(0.5*graph_ncritical_nodes(bmz->graph)) + 1);
|
||||||
graph_iterator_t it, it1;
|
graph_iterator_t it, it1;
|
||||||
|
|
||||||
DEBUGP("Labelling critical vertices\n");
|
DEBUGP("Labelling critical vertices\n");
|
||||||
bmz->g[v] = (uint32)ceil ((double)(*biggest_edge_value)/2) - 1;
|
bmz->g[v] = (uint32)ceil ((double)(*biggest_edge_value)/2) - 1;
|
||||||
|
SETBIT(visited, v);
|
||||||
next_g = (uint32)floor((double)(*biggest_edge_value/2)); /* next_g is incremented in the do..while statement*/
|
next_g = (uint32)floor((double)(*biggest_edge_value/2)); /* next_g is incremented in the do..while statement*/
|
||||||
*biggest_g_value = next_g;
|
|
||||||
vqueue_insert(q, v);
|
vqueue_insert(q, v);
|
||||||
while(!vqueue_is_empty(q))
|
while(!vqueue_is_empty(q))
|
||||||
{
|
{
|
||||||
@ -204,7 +221,7 @@ static void bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 *
|
|||||||
it = graph_neighbors_it(bmz->graph, v);
|
it = graph_neighbors_it(bmz->graph, v);
|
||||||
while ((u = graph_next_neighbor(bmz->graph, &it)) != GRAPH_NO_NEIGHBOR)
|
while ((u = graph_next_neighbor(bmz->graph, &it)) != GRAPH_NO_NEIGHBOR)
|
||||||
{
|
{
|
||||||
if (graph_node_is_critical(bmz->graph, u) && (bmz->g[u] == UNDEFINED))
|
if (graph_node_is_critical(bmz->graph, u) && (!GETBIT(visited,u)))
|
||||||
{
|
{
|
||||||
collision = 1;
|
collision = 1;
|
||||||
while(collision) // lookahead to resolve collisions
|
while(collision) // lookahead to resolve collisions
|
||||||
@ -214,9 +231,13 @@ static void bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 *
|
|||||||
collision = 0;
|
collision = 0;
|
||||||
while((lav = graph_next_neighbor(bmz->graph, &it1)) != GRAPH_NO_NEIGHBOR)
|
while((lav = graph_next_neighbor(bmz->graph, &it1)) != GRAPH_NO_NEIGHBOR)
|
||||||
{
|
{
|
||||||
if (graph_node_is_critical(bmz->graph, lav) && (bmz->g[lav] != UNDEFINED))
|
if (graph_node_is_critical(bmz->graph, lav) && GETBIT(visited,lav))
|
||||||
{
|
{
|
||||||
assert(next_g + bmz->g[lav] < bmz->m);
|
if(next_g + bmz->g[lav] >= bmz->m)
|
||||||
|
{
|
||||||
|
vqueue_destroy(q);
|
||||||
|
return 1; // restart mapping step.
|
||||||
|
}
|
||||||
if (GETBIT(used_edges, next_g + bmz->g[lav]))
|
if (GETBIT(used_edges, next_g + bmz->g[lav]))
|
||||||
{
|
{
|
||||||
collision = 1;
|
collision = 1;
|
||||||
@ -230,20 +251,115 @@ static void bmz_traverse_critical_nodes(bmz_mph_data_t *bmz, uint32 v, uint32 *
|
|||||||
it1 = graph_neighbors_it(bmz->graph, u);
|
it1 = graph_neighbors_it(bmz->graph, u);
|
||||||
while((lav = graph_next_neighbor(bmz->graph, &it1)) != GRAPH_NO_NEIGHBOR)
|
while((lav = graph_next_neighbor(bmz->graph, &it1)) != GRAPH_NO_NEIGHBOR)
|
||||||
{
|
{
|
||||||
if (graph_node_is_critical(bmz->graph, lav) && (bmz->g[lav] != UNDEFINED))
|
if (graph_node_is_critical(bmz->graph, lav) && GETBIT(visited, lav))
|
||||||
{
|
{
|
||||||
SETBIT(used_edges,next_g + bmz->g[lav]);
|
SETBIT(used_edges,next_g + bmz->g[lav]);
|
||||||
if(next_g + bmz->g[lav] > *biggest_edge_value) *biggest_edge_value = next_g + bmz->g[lav];
|
if(next_g + bmz->g[lav] > *biggest_edge_value) *biggest_edge_value = next_g + bmz->g[lav];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bmz->g[u] = next_g; // Labelling vertex u.
|
bmz->g[u] = next_g; // Labelling vertex u.
|
||||||
|
SETBIT(visited,u);
|
||||||
vqueue_insert(q, u);
|
vqueue_insert(q, u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
vqueue_destroy(q);
|
vqueue_destroy(q);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8 bmz_traverse_critical_nodes_heuristic(bmz_mph_data_t *bmz, uint32 v, uint32 * biggest_g_value, uint32 * biggest_edge_value, uint8 * used_edges, uint8 * visited)
|
||||||
|
{
|
||||||
|
uint32 next_g;
|
||||||
|
uint32 u; /* Auxiliary vertex */
|
||||||
|
uint32 lav; /* lookahead vertex */
|
||||||
|
uint8 collision;
|
||||||
|
uint32 * unused_g_values = NULL;
|
||||||
|
uint32 unused_g_values_capacity = 0;
|
||||||
|
uint32 nunused_g_values = 0;
|
||||||
|
vqueue_t * q = vqueue_new((uint32)(0.5*graph_ncritical_nodes(bmz->graph))+1);
|
||||||
|
graph_iterator_t it, it1;
|
||||||
|
|
||||||
|
DEBUGP("Labelling critical vertices\n");
|
||||||
|
bmz->g[v] = (uint32)ceil ((double)(*biggest_edge_value)/2) - 1;
|
||||||
|
SETBIT(visited, v);
|
||||||
|
next_g = (uint32)floor((double)(*biggest_edge_value/2)); /* next_g is incremented in the do..while statement*/
|
||||||
|
vqueue_insert(q, v);
|
||||||
|
while(!vqueue_is_empty(q))
|
||||||
|
{
|
||||||
|
v = vqueue_remove(q);
|
||||||
|
it = graph_neighbors_it(bmz->graph, v);
|
||||||
|
while ((u = graph_next_neighbor(bmz->graph, &it)) != GRAPH_NO_NEIGHBOR)
|
||||||
|
{
|
||||||
|
if (graph_node_is_critical(bmz->graph, u) && (!GETBIT(visited,u)))
|
||||||
|
{
|
||||||
|
uint32 next_g_index = 0;
|
||||||
|
collision = 1;
|
||||||
|
while(collision) // lookahead to resolve collisions
|
||||||
|
{
|
||||||
|
if (next_g_index < nunused_g_values)
|
||||||
|
{
|
||||||
|
next_g = unused_g_values[next_g_index++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_g = *biggest_g_value + 1;
|
||||||
|
next_g_index = UINT_MAX;
|
||||||
|
}
|
||||||
|
it1 = graph_neighbors_it(bmz->graph, u);
|
||||||
|
collision = 0;
|
||||||
|
while((lav = graph_next_neighbor(bmz->graph, &it1)) != GRAPH_NO_NEIGHBOR)
|
||||||
|
{
|
||||||
|
if (graph_node_is_critical(bmz->graph, lav) && GETBIT(visited,lav))
|
||||||
|
{
|
||||||
|
if(next_g + bmz->g[lav] >= bmz->m)
|
||||||
|
{
|
||||||
|
vqueue_destroy(q);
|
||||||
|
free(unused_g_values);
|
||||||
|
return 1; // restart mapping step.
|
||||||
|
}
|
||||||
|
if (GETBIT(used_edges, next_g + bmz->g[lav]))
|
||||||
|
{
|
||||||
|
collision = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(collision && (next_g > *biggest_g_value)) // saving the current g value stored in next_g.
|
||||||
|
{
|
||||||
|
if(nunused_g_values == unused_g_values_capacity)
|
||||||
|
{
|
||||||
|
unused_g_values = realloc(unused_g_values, (unused_g_values_capacity + BUFSIZ)*sizeof(uint32));
|
||||||
|
unused_g_values_capacity += BUFSIZ;
|
||||||
|
}
|
||||||
|
unused_g_values[nunused_g_values++] = next_g;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (next_g > *biggest_g_value) *biggest_g_value = next_g;
|
||||||
|
}
|
||||||
|
next_g_index--;
|
||||||
|
if (next_g_index < nunused_g_values) unused_g_values[next_g_index] = unused_g_values[--nunused_g_values];
|
||||||
|
|
||||||
|
// Marking used edges...
|
||||||
|
it1 = graph_neighbors_it(bmz->graph, u);
|
||||||
|
while((lav = graph_next_neighbor(bmz->graph, &it1)) != GRAPH_NO_NEIGHBOR)
|
||||||
|
{
|
||||||
|
if (graph_node_is_critical(bmz->graph, lav) && GETBIT(visited, lav))
|
||||||
|
{
|
||||||
|
SETBIT(used_edges,next_g + bmz->g[lav]);
|
||||||
|
if(next_g + bmz->g[lav] > *biggest_edge_value) *biggest_edge_value = next_g + bmz->g[lav];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bmz->g[u] = next_g; // Labelling vertex u.
|
||||||
|
SETBIT(visited, u);
|
||||||
|
vqueue_insert(q, u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
vqueue_destroy(q);
|
||||||
|
free(unused_g_values);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32 next_unused_edge(bmz_mph_data_t *bmz, uint8 * used_edges, uint32 unused_edge_index)
|
static uint32 next_unused_edge(bmz_mph_data_t *bmz, uint8 * used_edges, uint32 unused_edge_index)
|
||||||
@ -257,23 +373,24 @@ static uint32 next_unused_edge(bmz_mph_data_t *bmz, uint8 * used_edges, uint32 u
|
|||||||
return unused_edge_index;
|
return unused_edge_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bmz_traverse(bmz_mph_data_t *bmz, uint8 * used_edges, uint32 v, uint32 * unused_edge_index)
|
static void bmz_traverse(bmz_mph_data_t *bmz, uint8 * used_edges, uint32 v, uint32 * unused_edge_index, uint8 * visited)
|
||||||
{
|
{
|
||||||
graph_iterator_t it = graph_neighbors_it(bmz->graph, v);
|
graph_iterator_t it = graph_neighbors_it(bmz->graph, v);
|
||||||
uint32 neighbor = 0;
|
uint32 neighbor = 0;
|
||||||
while((neighbor = graph_next_neighbor(bmz->graph, &it)) != GRAPH_NO_NEIGHBOR)
|
while((neighbor = graph_next_neighbor(bmz->graph, &it)) != GRAPH_NO_NEIGHBOR)
|
||||||
{
|
{
|
||||||
|
if(GETBIT(visited,neighbor)) continue;
|
||||||
DEBUGP("Visiting neighbor %u\n", neighbor);
|
DEBUGP("Visiting neighbor %u\n", neighbor);
|
||||||
if(bmz->g[neighbor] != UNDEFINED) continue;
|
|
||||||
*unused_edge_index = next_unused_edge(bmz, used_edges, *unused_edge_index);
|
*unused_edge_index = next_unused_edge(bmz, used_edges, *unused_edge_index);
|
||||||
bmz->g[neighbor] = *unused_edge_index - bmz->g[v];
|
bmz->g[neighbor] = *unused_edge_index - bmz->g[v];
|
||||||
|
SETBIT(visited, neighbor);
|
||||||
(*unused_edge_index)++;
|
(*unused_edge_index)++;
|
||||||
bmz_traverse(bmz, used_edges, neighbor, unused_edge_index);
|
bmz_traverse(bmz, used_edges, neighbor, unused_edge_index, visited);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bmz_traverse_non_critical_nodes(bmz_mph_data_t *bmz, uint8 * used_edges)
|
static void bmz_traverse_non_critical_nodes(bmz_mph_data_t *bmz, uint8 * used_edges, uint8 * visited)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32 i, v1, v2, unused_edge_index = 0;
|
uint32 i, v1, v2, unused_edge_index = 0;
|
||||||
@ -282,17 +399,19 @@ static void bmz_traverse_non_critical_nodes(bmz_mph_data_t *bmz, uint8 * used_ed
|
|||||||
{
|
{
|
||||||
v1 = graph_vertex_id(bmz->graph, i, 0);
|
v1 = graph_vertex_id(bmz->graph, i, 0);
|
||||||
v2 = graph_vertex_id(bmz->graph, i, 1);
|
v2 = graph_vertex_id(bmz->graph, i, 1);
|
||||||
if((bmz->g[v1] != UNDEFINED && bmz->g[v2] != UNDEFINED) || (bmz->g[v1] == UNDEFINED && bmz->g[v2] == UNDEFINED)) continue;
|
if((GETBIT(visited,v1) && GETBIT(visited,v2)) || (!GETBIT(visited,v1) && !GETBIT(visited,v2))) continue;
|
||||||
if(bmz->g[v1] != UNDEFINED) bmz_traverse(bmz, used_edges, v1, &unused_edge_index);
|
if(GETBIT(visited,v1)) bmz_traverse(bmz, used_edges, v1, &unused_edge_index, visited);
|
||||||
else bmz_traverse(bmz, used_edges, v2, &unused_edge_index);
|
else bmz_traverse(bmz, used_edges, v2, &unused_edge_index, visited);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < bmz->n; i++)
|
for(i = 0; i < bmz->n; i++)
|
||||||
{
|
{
|
||||||
if(bmz->g[i] == UNDEFINED)
|
if(!GETBIT(visited,i))
|
||||||
{
|
{
|
||||||
bmz->g[i] = 0;
|
bmz->g[i] = 0;
|
||||||
bmz_traverse(bmz, used_edges, i, &unused_edge_index);
|
SETBIT(visited, i);
|
||||||
|
bmz_traverse(bmz, used_edges, i, &unused_edge_index, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,18 +69,18 @@ void mph_set_hashfuncs(mph_t *mph, CMPH_HASH *hashfuncs)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mphf_t *mph_create(mph_t *mph)
|
mphf_t *mph_create(mph_t *mph, float c)
|
||||||
{
|
{
|
||||||
mphf_t *mphf = NULL;
|
mphf_t *mphf = NULL;
|
||||||
switch (mph->algo)
|
switch (mph->algo)
|
||||||
{
|
{
|
||||||
case MPH_CZECH:
|
case MPH_CZECH:
|
||||||
DEBUGP("Creating czech hash\n");
|
DEBUGP("Creating czech hash\n");
|
||||||
mphf = czech_mph_create(mph, 2.09);
|
mphf = czech_mph_create(mph, c);
|
||||||
break;
|
break;
|
||||||
case MPH_BMZ: /* included -- Fabiano */
|
case MPH_BMZ: /* included -- Fabiano */
|
||||||
DEBUGP("Creating bmz hash\n");
|
DEBUGP("Creating bmz hash\n");
|
||||||
mphf = bmz_mph_create(mph, 1.15);
|
mphf = bmz_mph_create(mph, c);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -28,7 +28,7 @@ mph_t *mph_new(MPH_ALGO algo, key_source_t *key_source);
|
|||||||
void mph_set_hashfuncs(mph_t *mph, CMPH_HASH *hashfuncs);
|
void mph_set_hashfuncs(mph_t *mph, CMPH_HASH *hashfuncs);
|
||||||
void mph_set_verbosity(mph_t *mph, uint32 verbosity);
|
void mph_set_verbosity(mph_t *mph, uint32 verbosity);
|
||||||
void mph_destroy(mph_t *mph);
|
void mph_destroy(mph_t *mph);
|
||||||
mphf_t *mph_create(mph_t *mph);
|
mphf_t *mph_create(mph_t *mph, float c);
|
||||||
|
|
||||||
/** Hash querying API **/
|
/** Hash querying API **/
|
||||||
mphf_t *mphf_load(FILE *f);
|
mphf_t *mphf_load(FILE *f);
|
||||||
|
14
src/graph.c
14
src/graph.c
@ -10,7 +10,7 @@
|
|||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
static const char bitmask[8] = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
|
static uint8 bitmask[8] = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
|
||||||
#define GETBIT(array, i) (array[(i) / 8] & bitmask[(i) % 8])
|
#define GETBIT(array, i) (array[(i) / 8] & bitmask[(i) % 8])
|
||||||
#define SETBIT(array, i) (array[(i) / 8] |= bitmask[(i) % 8])
|
#define SETBIT(array, i) (array[(i) / 8] |= bitmask[(i) % 8])
|
||||||
#define UNSETBIT(array, i) (array[(i) / 8] &= (~(bitmask[(i) % 8])))
|
#define UNSETBIT(array, i) (array[(i) / 8] &= (~(bitmask[(i) % 8])))
|
||||||
@ -52,7 +52,7 @@ graph_t *graph_new(uint32 nnodes, uint32 nedges)
|
|||||||
|
|
||||||
void graph_destroy(graph_t *graph)
|
void graph_destroy(graph_t *graph)
|
||||||
{
|
{
|
||||||
DEBUGP("Destroying graph\n");
|
DEBUGP("Destroying graph\n");
|
||||||
free(graph->edges);
|
free(graph->edges);
|
||||||
free(graph->first);
|
free(graph->first);
|
||||||
free(graph->next);
|
free(graph->next);
|
||||||
@ -103,7 +103,7 @@ void graph_add_edge(graph_t *g, uint32 v1, uint32 v2)
|
|||||||
|
|
||||||
static int check_edge(graph_t *g, uint32 e, uint32 v1, uint32 v2)
|
static int check_edge(graph_t *g, uint32 e, uint32 v1, uint32 v2)
|
||||||
{
|
{
|
||||||
DEBUGP("Checking edge %u %u looking for %u %u\n", g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)], v1, v2);
|
DEBUGP("Checking edge %u %u looking for %u %u\n", g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)], v1, v2);
|
||||||
if (g->edges[abs_edge(e, 0)] == v1 && g->edges[abs_edge(e, 1)] == v2) return 1;
|
if (g->edges[abs_edge(e, 0)] == v1 && g->edges[abs_edge(e, 1)] == v2) return 1;
|
||||||
if (g->edges[abs_edge(e, 0)] == v2 && g->edges[abs_edge(e, 1)] == v1) return 1;
|
if (g->edges[abs_edge(e, 0)] == v2 && g->edges[abs_edge(e, 1)] == v1) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -207,7 +207,7 @@ static void cyclic_del_edge(graph_t *g, uint32 v, char *deleted)
|
|||||||
if (!degree1) return;
|
if (!degree1) return;
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
DEBUGP("Deleting edge %u (%u->%u)\n", e, g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)]);
|
DEBUGP("Deleting edge %u (%u->%u)\n", e, g->edges[abs_edge(e, 0)], g->edges[abs_edge(e, 1)]);
|
||||||
SETBIT(deleted, abs_edge(e, 0));
|
SETBIT(deleted, abs_edge(e, 0));
|
||||||
|
|
||||||
v2 = g->edges[abs_edge(e, 0)];
|
v2 = g->edges[abs_edge(e, 0)];
|
||||||
@ -217,7 +217,7 @@ static void cyclic_del_edge(graph_t *g, uint32 v, char *deleted)
|
|||||||
degree1 = find_degree1_edge(g, v2, deleted, &e);
|
degree1 = find_degree1_edge(g, v2, deleted, &e);
|
||||||
if (degree1)
|
if (degree1)
|
||||||
{
|
{
|
||||||
DEBUGP("Inspecting vertex %u\n", v2);
|
DEBUGP("Inspecting vertex %u\n", v2);
|
||||||
v1 = v2;
|
v1 = v2;
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
@ -240,7 +240,7 @@ int graph_is_cyclic(graph_t *g)
|
|||||||
{
|
{
|
||||||
if (!(GETBIT(deleted, i)))
|
if (!(GETBIT(deleted, i)))
|
||||||
{
|
{
|
||||||
DEBUGP("Edge %u %u->%u was not deleted\n", i, g->edges[i], g->edges[i + g->nedges]);
|
DEBUGP("Edge %u %u->%u was not deleted\n", i, g->edges[i], g->edges[i + g->nedges]);
|
||||||
free(deleted);
|
free(deleted);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -260,8 +260,10 @@ void graph_obtain_critical_nodes(graph_t *g) /* included -- Fabiano*/
|
|||||||
uint32 v;
|
uint32 v;
|
||||||
char *deleted = (char *)malloc((g->nedges*sizeof(char))/8+1);
|
char *deleted = (char *)malloc((g->nedges*sizeof(char))/8+1);
|
||||||
memset(deleted, 0, g->nedges/8 + 1);
|
memset(deleted, 0, g->nedges/8 + 1);
|
||||||
|
free(g->critical_nodes);
|
||||||
g->critical_nodes = (uint8 *)malloc((g->nnodes*sizeof(uint8))/8 + 1);
|
g->critical_nodes = (uint8 *)malloc((g->nnodes*sizeof(uint8))/8 + 1);
|
||||||
g->ncritical_nodes = 0;
|
g->ncritical_nodes = 0;
|
||||||
|
memset(g->critical_nodes, 0, (g->nnodes*sizeof(uint8))/8 + 1);
|
||||||
DEBUGP("Looking for the 2-core in graph with %u vertices and %u edges\n", g->nnodes, g->nedges);
|
DEBUGP("Looking for the 2-core in graph with %u vertices and %u edges\n", g->nnodes, g->nedges);
|
||||||
for (v = 0; v < g->nnodes; ++v)
|
for (v = 0; v < g->nnodes; ++v)
|
||||||
{
|
{
|
||||||
|
23
src/main.c
23
src/main.c
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
void usage(const char *prg)
|
void usage(const char *prg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: %s [-v] [-h] [-V] [-k] [-g [-s seed] ] [-m file.mph] [-a algorithm] keysfile\n", prg);
|
fprintf(stderr, "usage: %s [-v] [-h] [-V] [-k nkeys] [-g [-c value][-s seed] ] [-m file.mph] [-a algorithm] keysfile\n", prg);
|
||||||
}
|
}
|
||||||
void usage_long(const char *prg)
|
void usage_long(const char *prg)
|
||||||
{
|
{
|
||||||
@ -20,6 +20,7 @@ void usage_long(const char *prg)
|
|||||||
fprintf(stderr, "usage: %s [-v] [-h] [-V] [-k] [-g [-s seed] ] [-m file.mph] [-a algorithm] keysfile\n", prg);
|
fprintf(stderr, "usage: %s [-v] [-h] [-V] [-k] [-g [-s seed] ] [-m file.mph] [-a algorithm] keysfile\n", prg);
|
||||||
fprintf(stderr, "Minimum perfect hashing tool\n\n");
|
fprintf(stderr, "Minimum perfect hashing tool\n\n");
|
||||||
fprintf(stderr, " -h\t print this help message\n");
|
fprintf(stderr, " -h\t print this help message\n");
|
||||||
|
fprintf(stderr, " -c\t c value that determines the number of vertices in the graph\n");
|
||||||
fprintf(stderr, " -a\t algorithm - valid values are\n");
|
fprintf(stderr, " -a\t algorithm - valid values are\n");
|
||||||
for (i = 0; i < MPH_COUNT; ++i) fprintf(stderr, " \t * %s\n", mph_names[i]);
|
for (i = 0; i < MPH_COUNT; ++i) fprintf(stderr, " \t * %s\n", mph_names[i]);
|
||||||
fprintf(stderr, " -f\t hash function (may be used multiple times) - valid values are\n");
|
fprintf(stderr, " -f\t hash function (may be used multiple times) - valid values are\n");
|
||||||
@ -98,6 +99,7 @@ int main(int argc, char **argv)
|
|||||||
uint32 nhashes = 0;
|
uint32 nhashes = 0;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
MPH_ALGO mph_algo = MPH_CZECH;
|
MPH_ALGO mph_algo = MPH_CZECH;
|
||||||
|
float c = 2.09;
|
||||||
mph_t *mph = NULL;
|
mph_t *mph = NULL;
|
||||||
mphf_t *mphf = NULL;
|
mphf_t *mphf = NULL;
|
||||||
|
|
||||||
@ -105,9 +107,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
char c = getopt(argc, argv, "hVvk:a:f:gm:s:");
|
char ch = getopt(argc, argv, "hVvgc:k:a:f:m:s:");
|
||||||
if (c == -1) break;
|
if (ch == -1) break;
|
||||||
switch (c)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case 's':
|
case 's':
|
||||||
{
|
{
|
||||||
@ -119,6 +121,16 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
c = strtod(optarg, &endptr);
|
||||||
|
if(*endptr != 0) {
|
||||||
|
fprintf(stderr, "Invalid c value %s\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
generate = 1;
|
generate = 1;
|
||||||
break;
|
break;
|
||||||
@ -229,7 +241,8 @@ int main(int argc, char **argv)
|
|||||||
mph = mph_new(mph_algo, &source);
|
mph = mph_new(mph_algo, &source);
|
||||||
if (nhashes) mph_set_hashfuncs(mph, hashes);
|
if (nhashes) mph_set_hashfuncs(mph, hashes);
|
||||||
mph_set_verbosity(mph, verbosity);
|
mph_set_verbosity(mph, verbosity);
|
||||||
mphf = mph_create(mph);
|
if(mph_algo == MPH_BMZ && c >= 2.0) c=1.15;
|
||||||
|
mphf = mph_create(mph, c);
|
||||||
|
|
||||||
if (mphf == NULL)
|
if (mphf == NULL)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user