From 7eff4147a9ca4a9a0df70effc09d57ff565c5f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacobo=20Coll=20Morag=C3=B3n?= Date: Mon, 24 Jun 2013 19:36:44 +0200 Subject: [PATCH 1/3] Fix Bug in linked_list. Function implemented. Bugs at: linked_list_remove_at() //removing the first or last item linked_list_remove_last() //when size = 1 linked_list_remove_first() //idem Implemented: void* linked_list_remove(void *item, linked_list_t *linked_list_p) --- containers/linked_list.c | 45 +++++++++++++++++++++++++++++- containers/test/linked_list_test.c | 4 +++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/containers/linked_list.c b/containers/linked_list.c index cc3d7d8..c66296c 100644 --- a/containers/linked_list.c +++ b/containers/linked_list.c @@ -259,7 +259,41 @@ int linked_list_insert_all_at(size_t index, void** item_p, size_t num_items, lin void* linked_list_remove(void *item, linked_list_t *linked_list_p) { - return NULL; + assert(linked_list_p && item); + + if(linked_list_p->mode == COLLECTION_MODE_SYNCHRONIZED) { + pthread_mutex_lock(&linked_list_p->lock); + } + + linked_list_item_t* list_item = linked_list_p->first; + + while(list_item != NULL && list_item->item != item) { + list_item = list_item->next; + } + + if (list_item) { + if (list_item != linked_list_p->first) + list_item->prev->next = list_item->next; + else{ + if(linked_list_p->first = list_item->next) + list_item->next->prev = NULL; + } + if (list_item != linked_list_p->last) + list_item->next->prev = list_item->prev; + else{ + if(linked_list_p->last = list_item->prev) + list_item->prev->next = NULL; + } + + linked_list_p->size--; + + linked_list_item_free(list_item, NULL); + } + + if(linked_list_p->mode == COLLECTION_MODE_SYNCHRONIZED) { + pthread_mutex_unlock(&linked_list_p->lock); + } + return item; } void* linked_list_remove_first(linked_list_t *linked_list_p) { @@ -278,6 +312,8 @@ void* linked_list_remove_first(linked_list_t *linked_list_p) { if (linked_list_p->first) { linked_list_p->first->prev = NULL; } + else + linked_list_p->last = NULL; //jj linked_list_p->size--; item = list_item->item; linked_list_item_free(list_item, NULL); @@ -308,6 +344,8 @@ void* linked_list_remove_last(linked_list_t *linked_list_p) { if (linked_list_p->last) { linked_list_p->last->next = NULL; } + else + linked_list_p->first = NULL; //jj linked_list_p->size--; item = list_item->item; linked_list_item_free(list_item, NULL); @@ -327,6 +365,11 @@ void* linked_list_remove_at(size_t index, linked_list_t *linked_list_p) { void *item = NULL; if(index >= 0 && index < linked_list_p->size) { + if(index == 0) //jj + return linked_list_remove_first(linked_list_p); + if(index == linked_list_p->size-1) + return linked_list_remove_last(linked_list_p); + if(linked_list_p->mode == COLLECTION_MODE_SYNCHRONIZED) { pthread_mutex_lock(&linked_list_p->lock); } diff --git a/containers/test/linked_list_test.c b/containers/test/linked_list_test.c index 8a2fb0d..7fa8c25 100644 --- a/containers/test/linked_list_test.c +++ b/containers/test/linked_list_test.c @@ -47,6 +47,10 @@ START_TEST(test_insert_and_remove) { fail_if((int) linked_list_get_last(list) != 5, "Get: Position #5 (last) must contain number 5"); fail_if((int) linked_list_remove_first(list) != 0, "Remove: Position #0 (first) must contain number 0"); + fail_if((int) linked_list_insert_first(NULL, list) != 1, "Insert: Position #0"); + fail_if((int) linked_list_remove_at(0, list) != 0, "Remove: Position #0 must contain number 0"); + fail_if((int) linked_list_insert_last(NULL, list) != 1, "Insert: Position last"); + fail_if((int) linked_list_remove_at(linked_list_size(list)-1, list) != 0, "Remove: Position size-1(last) must contain number 0"); fail_if((int) linked_list_remove_last(list) != 5, "Remove: Position #5 (last) must contain number 5"); fail_if((int) linked_list_remove_at(2, list) != 3, "Remove: Position #2 must contain number 3"); From 316a8e4713d9720fef8de0ac0fa70975dbbb9253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacobo=20Coll=20Morag=C3=B3n?= Date: Mon, 24 Jun 2013 19:54:20 +0200 Subject: [PATCH 2/3] Graph first commit --- containers/graph.c | 752 ++++++++++++++++++++++++++++++ containers/graph.h | 165 +++++++ containers/test/SConscript | 25 +- containers/test/graph_test.c | 242 ++++++++++ containers/test/graph_time_test.c | 87 ++++ 5 files changed, 1270 insertions(+), 1 deletion(-) create mode 100644 containers/graph.c create mode 100644 containers/graph.h create mode 100644 containers/test/graph_test.c create mode 100644 containers/test/graph_time_test.c diff --git a/containers/graph.c b/containers/graph.c new file mode 100644 index 0000000..6c2f3d0 --- /dev/null +++ b/containers/graph.c @@ -0,0 +1,752 @@ +#include "graph.h" + +//TODO +// Test if graph_p != NULL + +#define GRAPH_MAX_NAME_LENGTH 256 + + +/** + * Creation and initialization + */ +graph_t* graph_new(char mask, int initial_num_vertices, int SYNC_MODE) +{ + graph_t *g = (graph_t*)malloc(sizeof(graph_t)); + + if((mask & GRAPH_MIXED_DIRECTED) == GRAPH_MIXED_DIRECTED) + g->directed = GRAPH_MIXED_DIRECTED; + else if(mask & GRAPH_DIRECTED) + g->directed = GRAPH_DIRECTED; + else + g->directed = GRAPH_NON_DIRECTED; //default value + + g->cyclic = (mask & GRAPH_ACYCLIC)? 0: 1; + //g->multiple = (mask & GRAPH_MULTIPLE)? 1: 0; + g->multiple = 0; + g->strict = mask & GRAPH_STRICT; + g->non_negative = mask & GRAPH_NON_NEGATIVE_WEIGHT; + + g->num_edges = 0; + g->num_vertices = 0; + + g->sync_mode = SYNC_MODE; + g->vertices = array_list_new(initial_num_vertices,1.5,SYNC_MODE); + g->removed_vertices = linked_list_new (SYNC_MODE); + g->dict = kh_init(gr); + + return g; + +} +/** + * Destruction + */ + +int graph_free(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + graph_clear(vertex_data_callback,edge_data_callback,graph_p); + array_list_free(graph_p->vertices, NULL); + linked_list_free(graph_p->removed_vertices, NULL); + kh_destroy(gr, graph_p->dict); + free(graph_p); +} + + +int graph_clear(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + int i; + vertex_t *v; + edge_t* e; + linked_list_iterator_t *iter; + + if(graph_p->num_vertices) + iter = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t)); + + for (i = 0; i < graph_p->num_vertices; i++) + { + + v = (vertex_t*)array_list_get(i, graph_p->vertices); + if(v->src == NULL){ + free(v); + continue; + } + if(edge_data_callback) + { + iter = linked_list_iterator_init(v->dst, iter); // free dst data + e = (edge_t*) linked_list_iterator_curr(iter); + + while (e != NULL) + { + edge_data_callback(e->data); + e = (edge_t*)linked_list_iterator_next(iter); + } + + + iter = linked_list_iterator_init(v->nd, iter); // free nd data and edge (only when e->src_id==-1, else sets to -1) + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + if(e->src_id != -1) + e->src_id = -1; + else{ + edge_data_callback(e->data); + free(e); + } + e = (edge_t*)linked_list_iterator_next(iter); + + } + } + else + { + iter = linked_list_iterator_init(v->nd, iter); // free nd edge (only when e->src_id==-1, else sets to -1) + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + if(e->src_id != -1) + e->src_id = -1; + else + free(e); + + e = (edge_t*)linked_list_iterator_next(iter); + } + } + + linked_list_free(v->src, NULL); + linked_list_free(v->dst, free); // free dst edge + linked_list_free(v->nd, NULL); + + free(v->name); + if(vertex_data_callback) + vertex_data_callback(v->data); + + free(v); + + + } + if(graph_p->num_vertices) + linked_list_iterator_free(iter); + array_list_clear(graph_p->vertices, NULL); + linked_list_clear(graph_p->removed_vertices, NULL); + + kh_clear(gr, graph_p->dict); + graph_p->num_edges = 0; + graph_p->num_vertices = 0; + +} + +/** + * Vertex Functions + */ + + +int graph_find_vertex(char* name, graph_t* graph_p){ + + khiter_t k = kh_get(gr,graph_p->dict,name); + + if(k == kh_end(graph_p->dict)) //If it was not found, ret -1 + return -1; + else + return kh_value(graph_p->dict, k); +} + +vertex_t* graph_get_vertex_s(char* vertex_name, graph_t * graph_p) +{ + int id = graph_find_vertex(vertex_name, graph_p); + if(id < 0) + return NULL; + else + return graph_get_vertex_i(id, graph_p); +} +vertex_t* graph_get_vertex_i(int vertex_id, graph_t * graph_p) +{ + vertex_t* v = NULL; + + if (vertex_id < graph_p->num_vertices && vertex_id >= 0) + { + v = (vertex_t*)array_list_get(vertex_id, graph_p->vertices); + if (v != NULL) + if (v->src == NULL) // v is in the removed_vertex list + v = NULL; + } + return v; +} + +int graph_exists_vertex_s(char* name, graph_t* graph_p) +{ + int id = graph_find_vertex(name, graph_p); + if(id >= 0) + { + return graph_exists_vertex_i(id, graph_p); + } + else + return -1; +} + +int graph_exists_vertex_i(int id, graph_t* graph_p) +{ + if( (id < graph_p->num_vertices || id >= 0 ) && graph_get_vertex_i(id, graph_p) != NULL) + return 0; + else + return -1; +} + + +int graph_reachable_vertex(int src, int dst, graph_t* graph_p){ + + if(src == dst) + return 0; + + linked_list_t* queue = linked_list_new(graph_p->sync_mode); + vertex_t* v, *v_dst; + edge_t *e; + linked_list_iterator_t *iter = (linked_list_iterator_t*)malloc(sizeof(linked_list_iterator_t)); + int i, fin = 0, dst_id; + char *c = (char*)calloc(graph_p->num_vertices, sizeof(char)); + + v = graph_get_vertex_i(src, graph_p); + v_dst = graph_get_vertex_i(dst, graph_p); + if(v != NULL && v_dst != NULL) + { + linked_list_insert_last(v, queue); + c[v->id] = 1; + while(v = (vertex_t*)linked_list_remove_first(queue)) + { + linked_list_iterator_init(v->dst, iter); + e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + if(c[e->dst_id]==0){ + if(e->dst_id == dst){ + fin = 1; + break; + } + linked_list_insert_last(graph_get_vertex_i(e->dst_id, graph_p),queue); + c[e->dst_id] = 1; + } + e=(edge_t*)linked_list_iterator_next(iter); + } + if(!fin){ + linked_list_iterator_init(v->nd, iter); + e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + dst_id = (e->dst_id != v->id)? e->dst_id: e->src_id; + if(c[dst_id]==0){ + if(dst_id == dst){ + fin = 1; + break; + } + linked_list_insert_last(graph_get_vertex_i(dst_id, graph_p),queue); + c[dst_id] = 1; + } + e=(edge_t*)linked_list_iterator_next(iter); + } + } + } + } + linked_list_iterator_free(iter); + linked_list_free(queue, NULL); + free(c); + return fin-1; +} + + +/*! + * @abstract + * + * @return >= 0 : vertex index + * -1 : Error at array_list_insert + * -2 : Error at kh_put. It already exists on the hash_table + * -3 : Error name == NULL + */ +int graph_add_vertex(char* name, void* vertex_data, graph_t* graph_p){ + + vertex_t *v; + + if (name==NULL) + return -3; + + if (linked_list_size(graph_p->removed_vertices)) + { + v = linked_list_get_first(graph_p->removed_vertices); + linked_list_remove_first(graph_p->removed_vertices); + } + else + { + v = (vertex_t*)malloc(sizeof(vertex_t)); + if(array_list_insert(v, graph_p->vertices) == 0){ + free(v); + return -1; + } + + graph_p->num_vertices++; + v->id = array_list_size(graph_p->vertices)-1; + } + //int id = graph_find_vertex(name, g); // Even if it already exists, it has to create a new one + + + int ret; + khiter_t k = kh_put(gr, graph_p->dict, name, &ret); + if (!ret){ + free(v); + kh_del(gr, graph_p->dict, k); + return -2; + } + //Created && appended OK + + + v->data = vertex_data; + + v->src = linked_list_new(graph_p->sync_mode); + v->dst = linked_list_new(graph_p->sync_mode); + v->nd = linked_list_new(graph_p->sync_mode); + + int length = strnlen(name,GRAPH_MAX_NAME_LENGTH)+1; + v->name = (char*)malloc(length); + strncpy(v->name, name, length); + + kh_value(graph_p->dict,k) = v->id; + + return v->id; +} + + +/** + * @return 0 OK + * -1 Not existing vertex + */ +int graph_remove_vertex_s(char* vertex_name, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + int vertex_id = graph_find_vertex(vertex_name,graph_p); + return graph_remove_vertex_i(vertex_id, vertex_data_callback, edge_data_callback, graph_p); +} +int graph_remove_vertex_i(int vertex_id, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + if(vertex_id < 0 || vertex_id >= graph_p->num_vertices) + return -1; + + vertex_t *v = graph_get_vertex_i(vertex_id, graph_p); + if(v == NULL) + return 0; + linked_list_iterator_t *iter = linked_list_iterator_new(v->src); + edge_t *e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + linked_list_iterator_next(iter); + graph_remove_edge_e(e, GRAPH_DIRECTED, edge_data_callback, graph_p); + e = (edge_t*)linked_list_iterator_curr(iter); + } + + iter = linked_list_iterator_init(v->dst, iter); + e = linked_list_iterator_curr(iter); + while(e != NULL) + { + linked_list_iterator_next(iter); + graph_remove_edge_e(e, GRAPH_DIRECTED, edge_data_callback, graph_p); + e = (edge_t*)linked_list_iterator_curr(iter); + } + + iter = linked_list_iterator_init(v->nd, iter); + e = linked_list_iterator_curr(iter); + while(e != NULL) + { + linked_list_iterator_next(iter); + graph_remove_edge_e(e, GRAPH_NON_DIRECTED, edge_data_callback, graph_p); + e = (edge_t*)linked_list_iterator_curr(iter); + } + linked_list_iterator_free(iter); + + linked_list_free(v->src, NULL); + linked_list_free(v->dst, NULL); // free dst edge + linked_list_free(v->nd, NULL); + v->src = v->dst = v->nd = NULL; + + kh_del(gr,graph_p->dict, kh_get(gr,graph_p->dict, v->name)); + + free(v->name); + v->name = NULL; + if(vertex_data_callback) + vertex_data_callback(v->data); + v->data = NULL; + linked_list_insert(v, graph_p->removed_vertices); + + return 0; +} + +/** + * Edge Functions + */ + +int graph_add_edge_i(int src, int dst, void* edge_data, char edge_type, graph_t* graph_p) +{ + return graph_add_edge_iw(src, dst, edge_data, edge_type, 1, graph_p); +} +int graph_add_edge_s(char* src, char* dst, void* edge_data, char edge_type, graph_t* graph_p) +{ + return graph_add_edge_sw(src, dst, edge_data, edge_type, 1, graph_p); +} +int graph_add_edge_sw(char* src, char* dst, void* edge_data, char edge_type, float weight, graph_t* graph_p) +{ + int s = graph_find_vertex(src,graph_p); + int d = graph_find_vertex(dst,graph_p); + return graph_add_edge_iw(s, d, edge_data, edge_type, weight, graph_p); +} + +/** + * + * + * @return 0 : OK + * -1 : src or dst are not in graph + * -2 : edge_type non supported + * -3 : edge_type non compatible with the graph directed type + * -4 : edge breaks acyclity + * -5 : edge breaks multiplicity + * -6 : Weight must be possitive + */ +int graph_add_edge_iw(int src, int dst, void* edge_data, char edge_type, float weight, graph_t* graph_p){ + + //if(array_list_size(graph_p->vertices) <= src || array_list_size(graph_p->vertices) <= dst || src < 0 || dst < 0) + // return -1; + if (graph_get_vertex_i(src, graph_p) == NULL || graph_get_vertex_i(src, graph_p) == NULL) + return -1; + + + edge_t * e; + + //if(!graph_p->multiple) + if(graph_get_edge_i(src,dst,edge_type, graph_p) != NULL) + return -5; + + if(!graph_p->cyclic && graph_p->strict){//if acyclic + if(edge_type == GRAPH_NON_DIRECTED) + if(graph_reachable_vertex(src, dst, graph_p)==0) + return -4; + if(graph_reachable_vertex(dst, src, graph_p)==0) + return -4; + } + + if(graph_p->non_negative && weight < 0) //FIXME weight < 0 || weight <= 0 ?? + return -6; + + //if(graph_exists_vertex_i(src, graph_p) < 0 || graph_exists_vertex_i(dst, graph_p) < 0 ) + // return -6; + + e = (edge_t*)malloc(sizeof(edge_t)); + e->src_id = src; + e->dst_id = dst; + e->data = edge_data; + e->weight = weight; + + switch(edge_type)// TODO comprobacion multiple... + { + case GRAPH_DIRECTED: + if(graph_p->directed == GRAPH_NON_DIRECTED && graph_p->strict == GRAPH_STRICT){ + free(e); + return -3; + } + + linked_list_insert(e,(graph_get_vertex_i(src,graph_p))->dst); + linked_list_insert(e,(graph_get_vertex_i(dst,graph_p))->src); + break; + case GRAPH_NON_DIRECTED: + if(graph_p->directed == GRAPH_DIRECTED && graph_p->strict == GRAPH_STRICT){ + free(e); + return -3; + } + linked_list_insert(e,(graph_get_vertex_i(src,graph_p))->nd); + linked_list_insert(e,(graph_get_vertex_i(dst,graph_p))->nd); + + break; + default: + free(e); + return -2; + } + graph_p->num_edges++; + return 0; + +} + + + +edge_t* graph_get_edge_s(char* src, char* dst, char edge_type, graph_t* graph_p) +{ + int s = graph_find_vertex(src,graph_p); + int d = graph_find_vertex(dst,graph_p); + if(s >= 0 && d >= 0) //opt + return graph_get_edge_i(s,d,edge_type, graph_p); + else + return NULL; +} + + +edge_t* graph_get_edge_i(int src, int dst, char edge_type, graph_t* graph_p) +{ + linked_list_iterator_t *iter; + + if(graph_exists_vertex_i(src, graph_p) < 0 || graph_exists_vertex_i(dst, graph_p) < 0 ) + return NULL; + + vertex_t *v = graph_get_vertex_i(src,graph_p); + edge_t *e; + if(edge_type == GRAPH_DIRECTED) + { + iter = linked_list_iterator_new(v->dst); + e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + if(e->dst_id == dst) + { + linked_list_iterator_free(iter); + return e; + } + e = (edge_t*)linked_list_iterator_next(iter); + } + linked_list_iterator_free(iter); + } + else if(edge_type == GRAPH_NON_DIRECTED){ + int nd_dst; + + iter = linked_list_iterator_new(v->nd); + e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + nd_dst = (e->src_id==src)? e->dst_id: e->src_id; + if(nd_dst == dst) + { + linked_list_iterator_free(iter); + return e; + } + e = (edge_t*)linked_list_iterator_next(iter); + } + linked_list_iterator_free(iter); + } + return NULL; +} + + +/*linked_list_t* graph_get_edge(int src, int dst, char edge_type, graph_t* graph_p) +{ + linked_list_t *l = linked_list_new(graph_p->sync_mode); + if(array_list_size(graph_p->vertices) <= src || array_list_size(graph_p->vertices) <= dst || src < 0 || dst < 0) + return l; + + linked_list_iterator_t *iter; + + vertex_t *v = (vertex_t*)graph_get_vertex_i(src,graph_p); + edge_t *e; + if(edge_type & GRAPH_DIRECTED) + { + iter = linked_list_iterator_new(v->dst); + e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + if(e->dst_id == dst) + { + linked_list_insert(e->data,l); + } + e = (edge_t*)linked_list_iterator_next(iter); + } + linked_list_iterator_free(iter); + } + if(edge_type & GRAPH_NON_DIRECTED) + { + int nd_dst; + + iter = linked_list_iterator_new(v->nd); + e = (edge_t*)linked_list_iterator_curr(iter); + while(e != NULL) + { + nd_dst = (e->src_id==src)? e->dst_id: e->src_id; + if(nd_dst == dst) + { + linked_list_insert(e->data,l); + } + e = (edge_t*)linked_list_iterator_next(iter); + } + linked_list_iterator_free(iter); + } + return l; +} +*/ + + +/** + * @return 0 OK + * -1 Edge doesn't exist + * -2 Corrupted edge + */ +int graph_remove_edge_s(char* src, char* dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + edge_t* e = graph_get_edge_s( src, dst, edge_type, graph_p); + if(e!=NULL) + return graph_remove_edge_e(e,edge_type, edge_data_callback, graph_p); + else + return -1; +} +int graph_remove_edge_i(int src, int dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + + edge_t *e = graph_get_edge_i( src, dst, edge_type, graph_p); + + if(e!=NULL) + return graph_remove_edge_e(e,edge_type, edge_data_callback, graph_p); + else + return -1; +} +int graph_remove_edge_e(edge_t *edge_p, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t* graph_p) +{ + if(edge_p == NULL) + return -1; + + + linked_list_iterator_t *iter; + vertex_t *v_src = graph_get_vertex_i(edge_p->src_id, graph_p); + vertex_t *v_dst = graph_get_vertex_i(edge_p->dst_id, graph_p); + if(v_src == NULL || v_dst == NULL) + return -2; + if(edge_type & GRAPH_DIRECTED){ + linked_list_remove(edge_p, v_src->dst); + linked_list_remove(edge_p, v_dst->src); + } + else if(edge_type & GRAPH_NON_DIRECTED) + { + linked_list_remove(edge_p, v_src->nd); + linked_list_remove(edge_p, v_dst->nd); + } + if(edge_data_callback) + edge_data_callback(edge_p->data); + free(edge_p); + graph_p->num_edges--; + return 0; +} + + + + +/** + * Others + */ + +int graph_print(graph_t* graph_p) +{ + int i; + vertex_t *v; + edge_t* e; + linked_list_iterator_t *iter; + if(graph_p->num_vertices) + iter = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t)); + + for (i = 0; i < graph_p->num_vertices; i++) + { + v = graph_get_vertex_i(i, graph_p); + if(v == NULL) + continue; + printf("%s _____ id(%d)\n src\n", v->name, v->id); + + iter = linked_list_iterator_init(v->src, iter); + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + printf ("\t%s <- %s\n" + , (graph_get_vertex_i(e->dst_id, graph_p))->name + , (graph_get_vertex_i(e->src_id, graph_p))->name); + e = (edge_t*)linked_list_iterator_next(iter); + } + printf(" dst\n"); + + iter = linked_list_iterator_init(v->dst, iter); + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + printf ("\t%s -> %s\n" + , (graph_get_vertex_i(e->src_id, graph_p))->name + , (graph_get_vertex_i(e->dst_id, graph_p))->name); + e = (edge_t*)linked_list_iterator_next(iter); + } + printf(" nd\n"); + + iter = linked_list_iterator_init(v->nd, iter); + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + printf ("\t%s -- %s\n" + , (graph_get_vertex_i(e->src_id, graph_p))->name + , (graph_get_vertex_i(e->dst_id, graph_p))->name); + e = (edge_t*)linked_list_iterator_next(iter); + } + printf("\n"); + printf("\n"); + } + + if(graph_p->num_vertices) + linked_list_iterator_free(iter); +} + + + +int graph_print_dot(char* file_name, graph_t* graph_p) +{ + FILE *f; + int i; + vertex_t *v; + edge_t* e; + linked_list_iterator_t *iter; + + if(file_name == NULL) + f = stdout; + else + f = fopen(file_name, "w"); + + if(graph_p->num_vertices) + iter = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t)); + + fprintf(f,"digraph {\n"); + + for (i = 0; i < graph_p->num_vertices; i++) + { + v = graph_get_vertex_i(i, graph_p); + if(v == NULL) + continue; + + if(!linked_list_size(v->src) && !linked_list_size(v->dst) && !linked_list_size(v->nd)) + fprintf(f,"\t%s;\n", v->name); + + iter = linked_list_iterator_init(v->dst, iter); + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + fprintf(f,"\t%s -> %s [label=\"%.2f\"];\n" + , (graph_get_vertex_i(e->src_id, graph_p))->name + , (graph_get_vertex_i(e->dst_id, graph_p))->name + , e->weight); + e = (edge_t*)linked_list_iterator_next(iter); + } + + iter = linked_list_iterator_init(v->nd, iter); + e = (edge_t*) linked_list_iterator_curr(iter); + while (e != NULL) + { + if( e->src_id == v->id) + { + fprintf(f,"\t%s -> %s [dir=none,label=\"%.2f\"];\n" + , (graph_get_vertex_i(e->src_id, graph_p))->name + , (graph_get_vertex_i(e->dst_id, graph_p))->name + , e->weight); + } + e = (edge_t*)linked_list_iterator_next(iter); + } + } + fprintf(f,"}\n"); + if(file_name != NULL) + fclose(f); + if(graph_p->num_vertices) + linked_list_iterator_free(iter); +} + +int graph_get_order (graph_t* graph_p) +{ + return graph_p->num_vertices - linked_list_size(graph_p->removed_vertices); +} +int graph_get_size (graph_t* graph_p) +{ + return graph_p->num_edges; +} diff --git a/containers/graph.h b/containers/graph.h new file mode 100644 index 0000000..c78faf5 --- /dev/null +++ b/containers/graph.h @@ -0,0 +1,165 @@ + +/** + * graph.h + * + * Podemos dar la opcion a cambiar el tipo de grafo despues de crearlo, + * es decir, si se permite el cambio automatico/manual de modo de grafo "si" "no" "depende" + * + * + * //typedef int vertex_id; ?? + * + * + * Hitos 2013-06-20: + * Tipos de parametros (_s, _i, _...) + * Elimina Goood + * Parser salida Good (con peso en aristas) + * graph_go no recursivo + * + * TODO: + * Darle coherencia + * check + * Correcto sincronismo (sync_mode) + * + * DUDAS: + * #define GRAPH_STRICT 0b00010000 + * check no pasa el valgrind + * add vertex sin nombre?? + * opcion a dar el peso o no? add_edge_iw, add_edge_i, add_edge_sw, add_edge_w + */ + +#ifndef _GRAPH_H_ +#define _GRAPH_H_ + + +#include "linked_list.h" +#include "array_list.h" +#include "containers.h" +#include "khash.h" + +KHASH_MAP_INIT_STR(gr,int) + + +typedef struct edge { + int src_id; + int dst_id; + void *data; + float weight; + //char* name; + +} edge_t; + +typedef int vertex_id_t; + +typedef struct vertex { + void *data; + linked_list_t *src; + linked_list_t *dst; + linked_list_t *nd; + char* name; + vertex_id_t id; +} vertex_t; + +typedef struct graph { + khash_t(gr) *dict; + array_list_t *vertices; + linked_list_t *removed_vertices; + int num_vertices; //() + int num_edges; //() + + short int directed; //si, no y mixto + short int cyclic; + short int multiple; + short int strict; + short int non_negative; + //reemplazar todo por una mascara? + + int sync_mode; +} graph_t; + + + +#define GRAPH_NON_DIRECTED 0b00000001 +#define GRAPH_DIRECTED 0b00000010 +#define GRAPH_MIXED_DIRECTED 0b00000011 +#define GRAPH_CYCLIC 0b00000000 +#define GRAPH_ACYCLIC 0b00000100 +#define GRAPH_STRICT 0b00001000 +#define GRAPH_NON_NEGATIVE_WEIGHT 0b00010000 +//#define GRAPH_MULTIPLE 0b00010000 + +/** + * Creation and initialization + */ +graph_t* graph_new(char mask, int initial_num_vertices, int SYNC_MODE); + +/** + * Destruction + */ + +int graph_free(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t*); + +int graph_clear(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t*); + +/** + * Vertex Functions + */ +int graph_add_vertex(char* name, void* vertex_data, graph_t*); + +int graph_find_vertex(char* name, graph_t*); // assumes only one ocurrence + +int graph_exists_vertex_s(char* name, graph_t*); +int graph_exists_vertex_i(int id, graph_t*); +//contains?? + +int graph_reachable_vertex(int src, int dst, graph_t*); + +vertex_t* graph_get_vertex_s(char* vertex_name, graph_t * graph_p); +vertex_t* graph_get_vertex_i(int vertex_id, graph_t * graph_p); + +void* graph_get_vertex_data_s(char* name, graph_t*); +void* graph_get_vertex_data_i(int id, graph_t*); +/* +linked_list_t* graph_vertex_neighborhood_s(char* name, graph_t*); +linked_list_t* graph_vertex_neighborhood_i(int id, graph_t*); + +linked_list_t* graph_vertex_neighborhood_out_s(char* name, graph_t*); +linked_list_t* graph_vertex_neighborhood_out_i(int id, graph_t*); + +linked_list_t* graph_vertex_neighborhood_in_s(char* name, graph_t*); +linked_list_t* graph_vertex_neighborhood_in_i(int id, graph_t*); +//adjacent +*/ + +int graph_remove_vertex_s(char* vertex_name, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t*); +int graph_remove_vertex_i(int vertex_id, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t*); + + +/** + * Edge Functions + */ +int graph_add_edge_s(char* src, char* dst, void* edge_data, char edge_type, graph_t*); +int graph_add_edge_i(int src, int dst, void* edge_data, char edge_type, graph_t*); +int graph_add_edge_sw(char* src, char* dst, void* edge_data, char edge_type, float weight, graph_t*); +int graph_add_edge_iw(int src, int dst, void* edge_data, char edge_type, float weight, graph_t*); + +int graph_remove_edge_s(char* src, char* dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t*); +int graph_remove_edge_i(int src, int dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t*); +int graph_remove_edge_e(edge_t *edge_p, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t*); + +edge_t* graph_get_edge_s(char* src, char* dst, char edge_type, graph_t*); +edge_t* graph_get_edge_i(int src, int dst, char edge_type, graph_t*); + +/** + * Path Functions + */ +//linked_list_t* graph_path_get(int src, int dst, graph_t*); + +/** + * Others + */ +int graph_print(graph_t*); +int graph_print_dot(char* file_name, graph_t*); +int graph_get_order (graph_t*); // vertex number +int graph_get_size (graph_t*); // edge number + +#endif //_GRAPH_H_ diff --git a/containers/test/SConscript b/containers/test/SConscript index a8aaf94..a60ef17 100644 --- a/containers/test/SConscript +++ b/containers/test/SConscript @@ -13,4 +13,27 @@ check_linked_list = env.Program('linked_list.test', source = ['linked_list_test.c', '%s/containers/linked_list.o' % commons_path ] - ) \ No newline at end of file + ) + + +env2 = Environment(CFLAGS = '-std=c99 -D_XOPEN_SOURCE=600 -D_GNU_SOURCE', + CPPPATH = ['#', commons_path, '/usr/include', '/usr/local/include', commons_path ], + LIBPATH = ['/usr/lib', '/usr/local/lib' ], + LIBS = ['check', 'curl', 'm', 'z', 'rt'] + ) +Import("debug") + +if debug == 1: + env2['CFLAGS'] += ' -O0 -g' +else: + env2['CFLAGS'] += ' -O3' + + +graph_time_test = env2.Program('graph_time_test', + ['graph_time_test.c', + '%s/commons/string_utils.o' % commons_path, + '%s/commons/log.o' % commons_path, + Glob('%s/containers/*.o' % commons_path), + Glob('%s/containers/cprops/*.o' % commons_path) + ] + ) diff --git a/containers/test/graph_test.c b/containers/test/graph_test.c new file mode 100644 index 0000000..8bbfc7d --- /dev/null +++ b/containers/test/graph_test.c @@ -0,0 +1,242 @@ + +#include +#include +#include + +#include "../graph.h" +graph_t *g; +Suite *create_test_suite(void); + +//************************** +// Checked fixtures * +//************************** + + +START_TEST(test_empty_graph) { + + g = graph_new(GRAPH_DIRECTED | GRAPH_CYCLIC, 20, COLLECTION_MODE_ASYNCHRONIZED); + + fail_if( graph_remove_vertex_i(0, NULL, NULL, g) != -1, "Removing inexistent vertex: return should be -1"); + fail_if( graph_remove_edge_i(0, 1, GRAPH_DIRECTED, NULL, g) != -1, "Removing inexistent vertex: return should be -1"); + fail_if( graph_remove_edge_i(0, 0, GRAPH_DIRECTED, NULL, g) != -1, "Removing inexistent vertex: return should be -1"); + + graph_free(NULL, NULL, g); +} +END_TEST + + +START_TEST(test_small_graph) { + + g = graph_new(GRAPH_DIRECTED | GRAPH_ACYCLIC |GRAPH_STRICT, 20, COLLECTION_MODE_ASYNCHRONIZED); + int ret = graph_add_vertex("A", NULL, g); + + fail_if( ret < 0, "add_vertex: return should be the new id but id=%d", ret); + ret = graph_add_vertex("B", NULL, g); + fail_if( ret < 0, "add_vertex: return should be the new id but id=%d", ret); + ret = graph_add_vertex("C", NULL, g); + fail_if( ret < 0, "add_vertex: return should be the new id but id=%d", ret); + + + ret = graph_add_edge_sw("A", "B", NULL, GRAPH_DIRECTED, 2, g); + fail_if( ret != 0, "add_vertex: return should be 0 but ret=%d", ret); + + ret = graph_add_edge_sw("D", "B", NULL, GRAPH_DIRECTED, 2, g); + fail_if( ret != -1, "add_vertex: non existent vertex: return should be -1 but ret=%d", ret); + + ret = graph_add_edge_sw("A", "C", NULL, 9, 2, g); + fail_if( ret != -2, "add_vertex: non supported edge type: return should be -2 but ret=%d", ret); + + ret = graph_add_edge_sw("C", "A", NULL, GRAPH_NON_DIRECTED, 2, g); + fail_if( ret != -3, "add_vertex: non compatible direction type: return should be -3 but ret=%d", ret); + + ret = graph_add_edge_sw("B", "B", NULL, GRAPH_DIRECTED, 2, g); + fail_if( ret != -4, "add_vertex: breaking acyclity: return should be -4 but ret=%d", ret); + + ret = graph_add_edge_sw("A", "B", NULL, GRAPH_DIRECTED, 2, g); + fail_if( ret != -5, "add_vertex: breaking multiplicity: return should be -5 but ret=%d", ret); + + ret = graph_add_edge_sw("C", "B", NULL, GRAPH_DIRECTED, 2, g); + fail_if( ret != 0, "add_vertex: return should be 0 but ret=%d", ret); + + //ret = graph_add_vertex(NULL, NULL, g); + //fail_if( ret < 10, "add_vertex: return should be the new id but id=%d", ret); + + graph_print(g); + + graph_print_dot("check_graph.gv", g); + + graph_free(NULL, NULL, g); +} +END_TEST + + +START_TEST(test_big_graph) { + +} +END_TEST + + +/* ****************************** + * Main entry point * + * ******************************/ + +int main (int argc, char *argv) { + Suite *fs = create_test_suite(); + SRunner *fs_runner = srunner_create(fs); + srunner_run_all(fs_runner, CK_NORMAL); + int number_failed = srunner_ntests_failed (fs_runner); + srunner_free (fs_runner); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + + +Suite *create_test_suite(void) { + TCase *tc_create_free = tcase_create("Create and free"); + + //tcase_add_checked_fixture(tc_create_free, create_graph, free_graph); + tcase_add_test(tc_create_free, test_empty_graph); + tcase_add_test(tc_create_free, test_small_graph); + tcase_add_test(tc_create_free, test_big_graph); + //tcase_add_test(tc_create_free, test_create_free); + + //TCase *tc_iterators = tcase_create("Iterators"); + //tcase_add_checked_fixture(tc_iterators, create_graph, free_graph); + //tcase_add_test(tc_iterators, test_iterators); + + // Add test cases to a test suite + Suite *fs = suite_create("Graph"); + suite_add_tcase(fs, tc_create_free); + //suite_add_tcase(fs, tc_iterators); + + return fs; +} + + + + + +/* + + + +#include +#include + +#include "../graph/graph.h" +graph_t *g; +void foo() +{ + + +} + +void free_cond(void* c) +{ + if(c) + free(c); +} + +void* new_mem(const char* c) +{ + return NULL; + char* v = malloc(20); + int i; + for(i = 0; i < 20 && c[i] != 0; i++) + v[i]=c[i]; + v[i] = 0; + return v; +} + +int main() +{ + printf("Holamundo\n"); + + g = graph_new(GRAPH_MIXED_DIRECTED | GRAPH_ACYCLIC, 20, COLLECTION_MODE_ASYNCHRONIZED); + + + graph_add_vertex("A", NULL, g); + graph_add_vertex("B", NULL, g); + graph_add_vertex("C", NULL, g); + graph_add_vertex("D", malloc(29), g); + + graph_add_edge_i(0,1, new_mem("Hola"), GRAPH_DIRECTED,2, g); + graph_add_edge_i(1,2, new_mem("Hola"), GRAPH_DIRECTED,2, g); + void* v = malloc(23); + if(graph_add_edge_i(2,0, v, GRAPH_DIRECTED,2, g)<0) + free(v); + + + graph_print(g); + printf("Clear\n"); + graph_clear(free_cond,free_cond,g); + + graph_add_vertex("A", NULL, g); + graph_add_vertex("S", NULL, g); + graph_add_vertex("D", NULL, g); + graph_add_vertex("F", NULL, g); + graph_add_vertex("G", NULL, g); + + graph_add_edge_s("A","S",NULL,GRAPH_DIRECTED,2,g); + graph_add_edge_s("S","D",NULL,GRAPH_DIRECTED,2,g); + graph_add_edge_s("S","D",NULL,GRAPH_DIRECTED,2,g); + graph_add_edge_s("G","D",NULL,GRAPH_DIRECTED,2,g); + graph_add_edge_s("A","D",NULL,GRAPH_NON_DIRECTED,2,g); + graph_add_edge_s("D","D",NULL,GRAPH_DIRECTED,2,g); + graph_add_edge_s("A","F",NULL,GRAPH_NON_DIRECTED,2,g); + + + graph_add_edge_s("F","G",new_mem("Pepe"),GRAPH_DIRECTED,2,g); + graph_add_edge_s("F","G",new_mem("Pepon"),GRAPH_DIRECTED,2,g); + graph_add_edge_s("F","G",new_mem("Null"),GRAPH_DIRECTED,2,g); + + + graph_add_edge_s("G","S",NULL,GRAPH_NON_DIRECTED,9,g); + graph_add_edge_s("F","S",NULL,GRAPH_DIRECTED,2,g); + + edge_t * e = graph_get_edge_i(3,4,GRAPH_DIRECTED,g); + if(e != NULL) + printf("Edge Tomado %s\n",(char*)e->data); + graph_remove_edge_e(e,GRAPH_DIRECTED,free_cond,g); + graph_remove_edge_s("A","S",GRAPH_DIRECTED,free_cond,g); + graph_remove_edge_s("A","Sasdfasd",GRAPH_DIRECTED,free_cond,g); + graph_remove_edge_s("A","G",GRAPH_DIRECTED,free_cond,g); + //printf("Edge Eliminado\n"); + + + //graph_print(g); + //printf("Go go to Eliminar vertice\n"); + //graph_remove_vertex_s("A",NULL,free_cond,g); + + //graph_add_vertex("GAUSON", NULL, g); +/* linked_list_iterator_t *iter = linked_list_iterator_new(l); + char* c = (char*)linked_list_iterator_curr(iter); + while(c != NULL) + { + printf("CHAR DEL LINKED : %s\n",c); + c = (char*)linked_list_iterator_next(iter); + + } + linked_list_iterator_free(iter); + linked_list_free(l, NULL); + */ + /* + graph_add_edge_s("GAUSON", "F", NULL, GRAPH_NON_DIRECTED,3.1415, g); + graph_add_edge_s("GAUSON", "F", NULL, GRAPH_DIRECTED,2, g); + graph_add_edge_s("F", "GAUSON", NULL, GRAPH_DIRECTED,1.618, g); + + + //graph_remove_vertex_s("dsfg",NULL,free_cond,g); + //graph_remove_vertex_s("S",NULL,free_cond,g); + + graph_print(g); + + graph_print_dot("grafo.gv",g); + + //printf("Existe camino entre 0 y 3? %d\n", graph_path_exists(0,3,g)); + + graph_free(NULL,free_cond,g); + + return 0; +} + +*/ diff --git a/containers/test/graph_time_test.c b/containers/test/graph_time_test.c new file mode 100644 index 0000000..d53f91d --- /dev/null +++ b/containers/test/graph_time_test.c @@ -0,0 +1,87 @@ +#include +//#include +#include "../graph.h" + +void stop_crono(char* mensaje, struct timespec * ini_time) +{ + struct timespec timedif, fin_time; + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &fin_time);//----------------------- + timedif.tv_sec = fin_time.tv_sec - ini_time->tv_sec; + timedif.tv_nsec = fin_time.tv_nsec - ini_time->tv_nsec; + if (timedif.tv_nsec < 0) + { + timedif.tv_nsec += 1000000000; + timedif.tv_sec--; + } + printf(mensaje, (int)timedif.tv_sec, timedif.tv_nsec); +} + +int main (void) +{ + struct timespec ini_time; + + graph_t *g; + int num_vertices = 1000000; + int num_edges = 10000000; + int name_length = 255; + char ** names; + int i; + + srand(time(NULL)); + + names = (char**) malloc (sizeof(char*)*num_vertices); + + for (i = 0; i < num_vertices; i++) + { + //itoa(i, names[i], 10); + names[i] = (char*) malloc (sizeof(char)*name_length); + sprintf(names[i], "%d", i); + //printf ("name[%d] = %s\n", i, names[i]); + } + + printf("grafo con %d nodos\n", num_vertices); + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++++ + + g = graph_new (GRAPH_CYCLIC | GRAPH_DIRECTED, num_vertices, COLLECTION_MODE_ASYNCHRONIZED); + + stop_crono("tiempo en crear el grafo: t = %d s y %ld ns\n", &ini_time);//----------------------- + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//++++++++++++++++++++++++++++++++++ + + for (i = 0; i < num_vertices; i++) + graph_add_vertex (names[i], NULL, g); + + stop_crono("tiempo rellenar vertices aleatorios: t = %d s y %ld ns\n", &ini_time);//----------------------- + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++ + + for (i = 0; i < num_edges; i++) + graph_add_edge_iw(rand()%num_vertices, rand()%num_vertices, NULL, GRAPH_DIRECTED, 1, g); + + stop_crono("tiempo en relenar edges aleatorios = %d s y %ld ns\n", &ini_time);//----------------- + + printf("solo cumplian las condiciones %d edges\n", g->num_edges); + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++++ + + graph_print_dot("grafo_tiempo.gv", g); + + stop_crono("tiempo en print dot: t = %d s y %ld ns\n", &ini_time);//----------------------- + + + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++++ + + graph_free(NULL, NULL, g); + + stop_crono("tiempo en liberar grafo: t = %d s y %ld ns\n", &ini_time);//----------------------- + + for (i = 0; i < num_vertices; i++) + free(names[i]); + + free (names); + + printf("\n"); + return 0; +} From 8ce674affe5a8bfdc4f5a6cae65963a925090247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacobo=20Coll=20Morag=C3=B3n?= Date: Tue, 23 Jul 2013 16:18:33 +0200 Subject: [PATCH 3/3] Revert "Graph first commit" This reverts commit 316a8e4713d9720fef8de0ac0fa70975dbbb9253. --- containers/graph.c | 752 ------------------------------ containers/graph.h | 165 ------- containers/test/SConscript | 25 +- containers/test/graph_test.c | 242 ---------- containers/test/graph_time_test.c | 87 ---- 5 files changed, 1 insertion(+), 1270 deletions(-) delete mode 100644 containers/graph.c delete mode 100644 containers/graph.h delete mode 100644 containers/test/graph_test.c delete mode 100644 containers/test/graph_time_test.c diff --git a/containers/graph.c b/containers/graph.c deleted file mode 100644 index 6c2f3d0..0000000 --- a/containers/graph.c +++ /dev/null @@ -1,752 +0,0 @@ -#include "graph.h" - -//TODO -// Test if graph_p != NULL - -#define GRAPH_MAX_NAME_LENGTH 256 - - -/** - * Creation and initialization - */ -graph_t* graph_new(char mask, int initial_num_vertices, int SYNC_MODE) -{ - graph_t *g = (graph_t*)malloc(sizeof(graph_t)); - - if((mask & GRAPH_MIXED_DIRECTED) == GRAPH_MIXED_DIRECTED) - g->directed = GRAPH_MIXED_DIRECTED; - else if(mask & GRAPH_DIRECTED) - g->directed = GRAPH_DIRECTED; - else - g->directed = GRAPH_NON_DIRECTED; //default value - - g->cyclic = (mask & GRAPH_ACYCLIC)? 0: 1; - //g->multiple = (mask & GRAPH_MULTIPLE)? 1: 0; - g->multiple = 0; - g->strict = mask & GRAPH_STRICT; - g->non_negative = mask & GRAPH_NON_NEGATIVE_WEIGHT; - - g->num_edges = 0; - g->num_vertices = 0; - - g->sync_mode = SYNC_MODE; - g->vertices = array_list_new(initial_num_vertices,1.5,SYNC_MODE); - g->removed_vertices = linked_list_new (SYNC_MODE); - g->dict = kh_init(gr); - - return g; - -} -/** - * Destruction - */ - -int graph_free(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - graph_clear(vertex_data_callback,edge_data_callback,graph_p); - array_list_free(graph_p->vertices, NULL); - linked_list_free(graph_p->removed_vertices, NULL); - kh_destroy(gr, graph_p->dict); - free(graph_p); -} - - -int graph_clear(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - int i; - vertex_t *v; - edge_t* e; - linked_list_iterator_t *iter; - - if(graph_p->num_vertices) - iter = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t)); - - for (i = 0; i < graph_p->num_vertices; i++) - { - - v = (vertex_t*)array_list_get(i, graph_p->vertices); - if(v->src == NULL){ - free(v); - continue; - } - if(edge_data_callback) - { - iter = linked_list_iterator_init(v->dst, iter); // free dst data - e = (edge_t*) linked_list_iterator_curr(iter); - - while (e != NULL) - { - edge_data_callback(e->data); - e = (edge_t*)linked_list_iterator_next(iter); - } - - - iter = linked_list_iterator_init(v->nd, iter); // free nd data and edge (only when e->src_id==-1, else sets to -1) - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - if(e->src_id != -1) - e->src_id = -1; - else{ - edge_data_callback(e->data); - free(e); - } - e = (edge_t*)linked_list_iterator_next(iter); - - } - } - else - { - iter = linked_list_iterator_init(v->nd, iter); // free nd edge (only when e->src_id==-1, else sets to -1) - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - if(e->src_id != -1) - e->src_id = -1; - else - free(e); - - e = (edge_t*)linked_list_iterator_next(iter); - } - } - - linked_list_free(v->src, NULL); - linked_list_free(v->dst, free); // free dst edge - linked_list_free(v->nd, NULL); - - free(v->name); - if(vertex_data_callback) - vertex_data_callback(v->data); - - free(v); - - - } - if(graph_p->num_vertices) - linked_list_iterator_free(iter); - array_list_clear(graph_p->vertices, NULL); - linked_list_clear(graph_p->removed_vertices, NULL); - - kh_clear(gr, graph_p->dict); - graph_p->num_edges = 0; - graph_p->num_vertices = 0; - -} - -/** - * Vertex Functions - */ - - -int graph_find_vertex(char* name, graph_t* graph_p){ - - khiter_t k = kh_get(gr,graph_p->dict,name); - - if(k == kh_end(graph_p->dict)) //If it was not found, ret -1 - return -1; - else - return kh_value(graph_p->dict, k); -} - -vertex_t* graph_get_vertex_s(char* vertex_name, graph_t * graph_p) -{ - int id = graph_find_vertex(vertex_name, graph_p); - if(id < 0) - return NULL; - else - return graph_get_vertex_i(id, graph_p); -} -vertex_t* graph_get_vertex_i(int vertex_id, graph_t * graph_p) -{ - vertex_t* v = NULL; - - if (vertex_id < graph_p->num_vertices && vertex_id >= 0) - { - v = (vertex_t*)array_list_get(vertex_id, graph_p->vertices); - if (v != NULL) - if (v->src == NULL) // v is in the removed_vertex list - v = NULL; - } - return v; -} - -int graph_exists_vertex_s(char* name, graph_t* graph_p) -{ - int id = graph_find_vertex(name, graph_p); - if(id >= 0) - { - return graph_exists_vertex_i(id, graph_p); - } - else - return -1; -} - -int graph_exists_vertex_i(int id, graph_t* graph_p) -{ - if( (id < graph_p->num_vertices || id >= 0 ) && graph_get_vertex_i(id, graph_p) != NULL) - return 0; - else - return -1; -} - - -int graph_reachable_vertex(int src, int dst, graph_t* graph_p){ - - if(src == dst) - return 0; - - linked_list_t* queue = linked_list_new(graph_p->sync_mode); - vertex_t* v, *v_dst; - edge_t *e; - linked_list_iterator_t *iter = (linked_list_iterator_t*)malloc(sizeof(linked_list_iterator_t)); - int i, fin = 0, dst_id; - char *c = (char*)calloc(graph_p->num_vertices, sizeof(char)); - - v = graph_get_vertex_i(src, graph_p); - v_dst = graph_get_vertex_i(dst, graph_p); - if(v != NULL && v_dst != NULL) - { - linked_list_insert_last(v, queue); - c[v->id] = 1; - while(v = (vertex_t*)linked_list_remove_first(queue)) - { - linked_list_iterator_init(v->dst, iter); - e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - if(c[e->dst_id]==0){ - if(e->dst_id == dst){ - fin = 1; - break; - } - linked_list_insert_last(graph_get_vertex_i(e->dst_id, graph_p),queue); - c[e->dst_id] = 1; - } - e=(edge_t*)linked_list_iterator_next(iter); - } - if(!fin){ - linked_list_iterator_init(v->nd, iter); - e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - dst_id = (e->dst_id != v->id)? e->dst_id: e->src_id; - if(c[dst_id]==0){ - if(dst_id == dst){ - fin = 1; - break; - } - linked_list_insert_last(graph_get_vertex_i(dst_id, graph_p),queue); - c[dst_id] = 1; - } - e=(edge_t*)linked_list_iterator_next(iter); - } - } - } - } - linked_list_iterator_free(iter); - linked_list_free(queue, NULL); - free(c); - return fin-1; -} - - -/*! - * @abstract - * - * @return >= 0 : vertex index - * -1 : Error at array_list_insert - * -2 : Error at kh_put. It already exists on the hash_table - * -3 : Error name == NULL - */ -int graph_add_vertex(char* name, void* vertex_data, graph_t* graph_p){ - - vertex_t *v; - - if (name==NULL) - return -3; - - if (linked_list_size(graph_p->removed_vertices)) - { - v = linked_list_get_first(graph_p->removed_vertices); - linked_list_remove_first(graph_p->removed_vertices); - } - else - { - v = (vertex_t*)malloc(sizeof(vertex_t)); - if(array_list_insert(v, graph_p->vertices) == 0){ - free(v); - return -1; - } - - graph_p->num_vertices++; - v->id = array_list_size(graph_p->vertices)-1; - } - //int id = graph_find_vertex(name, g); // Even if it already exists, it has to create a new one - - - int ret; - khiter_t k = kh_put(gr, graph_p->dict, name, &ret); - if (!ret){ - free(v); - kh_del(gr, graph_p->dict, k); - return -2; - } - //Created && appended OK - - - v->data = vertex_data; - - v->src = linked_list_new(graph_p->sync_mode); - v->dst = linked_list_new(graph_p->sync_mode); - v->nd = linked_list_new(graph_p->sync_mode); - - int length = strnlen(name,GRAPH_MAX_NAME_LENGTH)+1; - v->name = (char*)malloc(length); - strncpy(v->name, name, length); - - kh_value(graph_p->dict,k) = v->id; - - return v->id; -} - - -/** - * @return 0 OK - * -1 Not existing vertex - */ -int graph_remove_vertex_s(char* vertex_name, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - int vertex_id = graph_find_vertex(vertex_name,graph_p); - return graph_remove_vertex_i(vertex_id, vertex_data_callback, edge_data_callback, graph_p); -} -int graph_remove_vertex_i(int vertex_id, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - if(vertex_id < 0 || vertex_id >= graph_p->num_vertices) - return -1; - - vertex_t *v = graph_get_vertex_i(vertex_id, graph_p); - if(v == NULL) - return 0; - linked_list_iterator_t *iter = linked_list_iterator_new(v->src); - edge_t *e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - linked_list_iterator_next(iter); - graph_remove_edge_e(e, GRAPH_DIRECTED, edge_data_callback, graph_p); - e = (edge_t*)linked_list_iterator_curr(iter); - } - - iter = linked_list_iterator_init(v->dst, iter); - e = linked_list_iterator_curr(iter); - while(e != NULL) - { - linked_list_iterator_next(iter); - graph_remove_edge_e(e, GRAPH_DIRECTED, edge_data_callback, graph_p); - e = (edge_t*)linked_list_iterator_curr(iter); - } - - iter = linked_list_iterator_init(v->nd, iter); - e = linked_list_iterator_curr(iter); - while(e != NULL) - { - linked_list_iterator_next(iter); - graph_remove_edge_e(e, GRAPH_NON_DIRECTED, edge_data_callback, graph_p); - e = (edge_t*)linked_list_iterator_curr(iter); - } - linked_list_iterator_free(iter); - - linked_list_free(v->src, NULL); - linked_list_free(v->dst, NULL); // free dst edge - linked_list_free(v->nd, NULL); - v->src = v->dst = v->nd = NULL; - - kh_del(gr,graph_p->dict, kh_get(gr,graph_p->dict, v->name)); - - free(v->name); - v->name = NULL; - if(vertex_data_callback) - vertex_data_callback(v->data); - v->data = NULL; - linked_list_insert(v, graph_p->removed_vertices); - - return 0; -} - -/** - * Edge Functions - */ - -int graph_add_edge_i(int src, int dst, void* edge_data, char edge_type, graph_t* graph_p) -{ - return graph_add_edge_iw(src, dst, edge_data, edge_type, 1, graph_p); -} -int graph_add_edge_s(char* src, char* dst, void* edge_data, char edge_type, graph_t* graph_p) -{ - return graph_add_edge_sw(src, dst, edge_data, edge_type, 1, graph_p); -} -int graph_add_edge_sw(char* src, char* dst, void* edge_data, char edge_type, float weight, graph_t* graph_p) -{ - int s = graph_find_vertex(src,graph_p); - int d = graph_find_vertex(dst,graph_p); - return graph_add_edge_iw(s, d, edge_data, edge_type, weight, graph_p); -} - -/** - * - * - * @return 0 : OK - * -1 : src or dst are not in graph - * -2 : edge_type non supported - * -3 : edge_type non compatible with the graph directed type - * -4 : edge breaks acyclity - * -5 : edge breaks multiplicity - * -6 : Weight must be possitive - */ -int graph_add_edge_iw(int src, int dst, void* edge_data, char edge_type, float weight, graph_t* graph_p){ - - //if(array_list_size(graph_p->vertices) <= src || array_list_size(graph_p->vertices) <= dst || src < 0 || dst < 0) - // return -1; - if (graph_get_vertex_i(src, graph_p) == NULL || graph_get_vertex_i(src, graph_p) == NULL) - return -1; - - - edge_t * e; - - //if(!graph_p->multiple) - if(graph_get_edge_i(src,dst,edge_type, graph_p) != NULL) - return -5; - - if(!graph_p->cyclic && graph_p->strict){//if acyclic - if(edge_type == GRAPH_NON_DIRECTED) - if(graph_reachable_vertex(src, dst, graph_p)==0) - return -4; - if(graph_reachable_vertex(dst, src, graph_p)==0) - return -4; - } - - if(graph_p->non_negative && weight < 0) //FIXME weight < 0 || weight <= 0 ?? - return -6; - - //if(graph_exists_vertex_i(src, graph_p) < 0 || graph_exists_vertex_i(dst, graph_p) < 0 ) - // return -6; - - e = (edge_t*)malloc(sizeof(edge_t)); - e->src_id = src; - e->dst_id = dst; - e->data = edge_data; - e->weight = weight; - - switch(edge_type)// TODO comprobacion multiple... - { - case GRAPH_DIRECTED: - if(graph_p->directed == GRAPH_NON_DIRECTED && graph_p->strict == GRAPH_STRICT){ - free(e); - return -3; - } - - linked_list_insert(e,(graph_get_vertex_i(src,graph_p))->dst); - linked_list_insert(e,(graph_get_vertex_i(dst,graph_p))->src); - break; - case GRAPH_NON_DIRECTED: - if(graph_p->directed == GRAPH_DIRECTED && graph_p->strict == GRAPH_STRICT){ - free(e); - return -3; - } - linked_list_insert(e,(graph_get_vertex_i(src,graph_p))->nd); - linked_list_insert(e,(graph_get_vertex_i(dst,graph_p))->nd); - - break; - default: - free(e); - return -2; - } - graph_p->num_edges++; - return 0; - -} - - - -edge_t* graph_get_edge_s(char* src, char* dst, char edge_type, graph_t* graph_p) -{ - int s = graph_find_vertex(src,graph_p); - int d = graph_find_vertex(dst,graph_p); - if(s >= 0 && d >= 0) //opt - return graph_get_edge_i(s,d,edge_type, graph_p); - else - return NULL; -} - - -edge_t* graph_get_edge_i(int src, int dst, char edge_type, graph_t* graph_p) -{ - linked_list_iterator_t *iter; - - if(graph_exists_vertex_i(src, graph_p) < 0 || graph_exists_vertex_i(dst, graph_p) < 0 ) - return NULL; - - vertex_t *v = graph_get_vertex_i(src,graph_p); - edge_t *e; - if(edge_type == GRAPH_DIRECTED) - { - iter = linked_list_iterator_new(v->dst); - e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - if(e->dst_id == dst) - { - linked_list_iterator_free(iter); - return e; - } - e = (edge_t*)linked_list_iterator_next(iter); - } - linked_list_iterator_free(iter); - } - else if(edge_type == GRAPH_NON_DIRECTED){ - int nd_dst; - - iter = linked_list_iterator_new(v->nd); - e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - nd_dst = (e->src_id==src)? e->dst_id: e->src_id; - if(nd_dst == dst) - { - linked_list_iterator_free(iter); - return e; - } - e = (edge_t*)linked_list_iterator_next(iter); - } - linked_list_iterator_free(iter); - } - return NULL; -} - - -/*linked_list_t* graph_get_edge(int src, int dst, char edge_type, graph_t* graph_p) -{ - linked_list_t *l = linked_list_new(graph_p->sync_mode); - if(array_list_size(graph_p->vertices) <= src || array_list_size(graph_p->vertices) <= dst || src < 0 || dst < 0) - return l; - - linked_list_iterator_t *iter; - - vertex_t *v = (vertex_t*)graph_get_vertex_i(src,graph_p); - edge_t *e; - if(edge_type & GRAPH_DIRECTED) - { - iter = linked_list_iterator_new(v->dst); - e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - if(e->dst_id == dst) - { - linked_list_insert(e->data,l); - } - e = (edge_t*)linked_list_iterator_next(iter); - } - linked_list_iterator_free(iter); - } - if(edge_type & GRAPH_NON_DIRECTED) - { - int nd_dst; - - iter = linked_list_iterator_new(v->nd); - e = (edge_t*)linked_list_iterator_curr(iter); - while(e != NULL) - { - nd_dst = (e->src_id==src)? e->dst_id: e->src_id; - if(nd_dst == dst) - { - linked_list_insert(e->data,l); - } - e = (edge_t*)linked_list_iterator_next(iter); - } - linked_list_iterator_free(iter); - } - return l; -} -*/ - - -/** - * @return 0 OK - * -1 Edge doesn't exist - * -2 Corrupted edge - */ -int graph_remove_edge_s(char* src, char* dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - edge_t* e = graph_get_edge_s( src, dst, edge_type, graph_p); - if(e!=NULL) - return graph_remove_edge_e(e,edge_type, edge_data_callback, graph_p); - else - return -1; -} -int graph_remove_edge_i(int src, int dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - - edge_t *e = graph_get_edge_i( src, dst, edge_type, graph_p); - - if(e!=NULL) - return graph_remove_edge_e(e,edge_type, edge_data_callback, graph_p); - else - return -1; -} -int graph_remove_edge_e(edge_t *edge_p, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t* graph_p) -{ - if(edge_p == NULL) - return -1; - - - linked_list_iterator_t *iter; - vertex_t *v_src = graph_get_vertex_i(edge_p->src_id, graph_p); - vertex_t *v_dst = graph_get_vertex_i(edge_p->dst_id, graph_p); - if(v_src == NULL || v_dst == NULL) - return -2; - if(edge_type & GRAPH_DIRECTED){ - linked_list_remove(edge_p, v_src->dst); - linked_list_remove(edge_p, v_dst->src); - } - else if(edge_type & GRAPH_NON_DIRECTED) - { - linked_list_remove(edge_p, v_src->nd); - linked_list_remove(edge_p, v_dst->nd); - } - if(edge_data_callback) - edge_data_callback(edge_p->data); - free(edge_p); - graph_p->num_edges--; - return 0; -} - - - - -/** - * Others - */ - -int graph_print(graph_t* graph_p) -{ - int i; - vertex_t *v; - edge_t* e; - linked_list_iterator_t *iter; - if(graph_p->num_vertices) - iter = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t)); - - for (i = 0; i < graph_p->num_vertices; i++) - { - v = graph_get_vertex_i(i, graph_p); - if(v == NULL) - continue; - printf("%s _____ id(%d)\n src\n", v->name, v->id); - - iter = linked_list_iterator_init(v->src, iter); - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - printf ("\t%s <- %s\n" - , (graph_get_vertex_i(e->dst_id, graph_p))->name - , (graph_get_vertex_i(e->src_id, graph_p))->name); - e = (edge_t*)linked_list_iterator_next(iter); - } - printf(" dst\n"); - - iter = linked_list_iterator_init(v->dst, iter); - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - printf ("\t%s -> %s\n" - , (graph_get_vertex_i(e->src_id, graph_p))->name - , (graph_get_vertex_i(e->dst_id, graph_p))->name); - e = (edge_t*)linked_list_iterator_next(iter); - } - printf(" nd\n"); - - iter = linked_list_iterator_init(v->nd, iter); - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - printf ("\t%s -- %s\n" - , (graph_get_vertex_i(e->src_id, graph_p))->name - , (graph_get_vertex_i(e->dst_id, graph_p))->name); - e = (edge_t*)linked_list_iterator_next(iter); - } - printf("\n"); - printf("\n"); - } - - if(graph_p->num_vertices) - linked_list_iterator_free(iter); -} - - - -int graph_print_dot(char* file_name, graph_t* graph_p) -{ - FILE *f; - int i; - vertex_t *v; - edge_t* e; - linked_list_iterator_t *iter; - - if(file_name == NULL) - f = stdout; - else - f = fopen(file_name, "w"); - - if(graph_p->num_vertices) - iter = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t)); - - fprintf(f,"digraph {\n"); - - for (i = 0; i < graph_p->num_vertices; i++) - { - v = graph_get_vertex_i(i, graph_p); - if(v == NULL) - continue; - - if(!linked_list_size(v->src) && !linked_list_size(v->dst) && !linked_list_size(v->nd)) - fprintf(f,"\t%s;\n", v->name); - - iter = linked_list_iterator_init(v->dst, iter); - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - fprintf(f,"\t%s -> %s [label=\"%.2f\"];\n" - , (graph_get_vertex_i(e->src_id, graph_p))->name - , (graph_get_vertex_i(e->dst_id, graph_p))->name - , e->weight); - e = (edge_t*)linked_list_iterator_next(iter); - } - - iter = linked_list_iterator_init(v->nd, iter); - e = (edge_t*) linked_list_iterator_curr(iter); - while (e != NULL) - { - if( e->src_id == v->id) - { - fprintf(f,"\t%s -> %s [dir=none,label=\"%.2f\"];\n" - , (graph_get_vertex_i(e->src_id, graph_p))->name - , (graph_get_vertex_i(e->dst_id, graph_p))->name - , e->weight); - } - e = (edge_t*)linked_list_iterator_next(iter); - } - } - fprintf(f,"}\n"); - if(file_name != NULL) - fclose(f); - if(graph_p->num_vertices) - linked_list_iterator_free(iter); -} - -int graph_get_order (graph_t* graph_p) -{ - return graph_p->num_vertices - linked_list_size(graph_p->removed_vertices); -} -int graph_get_size (graph_t* graph_p) -{ - return graph_p->num_edges; -} diff --git a/containers/graph.h b/containers/graph.h deleted file mode 100644 index c78faf5..0000000 --- a/containers/graph.h +++ /dev/null @@ -1,165 +0,0 @@ - -/** - * graph.h - * - * Podemos dar la opcion a cambiar el tipo de grafo despues de crearlo, - * es decir, si se permite el cambio automatico/manual de modo de grafo "si" "no" "depende" - * - * - * //typedef int vertex_id; ?? - * - * - * Hitos 2013-06-20: - * Tipos de parametros (_s, _i, _...) - * Elimina Goood - * Parser salida Good (con peso en aristas) - * graph_go no recursivo - * - * TODO: - * Darle coherencia - * check - * Correcto sincronismo (sync_mode) - * - * DUDAS: - * #define GRAPH_STRICT 0b00010000 - * check no pasa el valgrind - * add vertex sin nombre?? - * opcion a dar el peso o no? add_edge_iw, add_edge_i, add_edge_sw, add_edge_w - */ - -#ifndef _GRAPH_H_ -#define _GRAPH_H_ - - -#include "linked_list.h" -#include "array_list.h" -#include "containers.h" -#include "khash.h" - -KHASH_MAP_INIT_STR(gr,int) - - -typedef struct edge { - int src_id; - int dst_id; - void *data; - float weight; - //char* name; - -} edge_t; - -typedef int vertex_id_t; - -typedef struct vertex { - void *data; - linked_list_t *src; - linked_list_t *dst; - linked_list_t *nd; - char* name; - vertex_id_t id; -} vertex_t; - -typedef struct graph { - khash_t(gr) *dict; - array_list_t *vertices; - linked_list_t *removed_vertices; - int num_vertices; //() - int num_edges; //() - - short int directed; //si, no y mixto - short int cyclic; - short int multiple; - short int strict; - short int non_negative; - //reemplazar todo por una mascara? - - int sync_mode; -} graph_t; - - - -#define GRAPH_NON_DIRECTED 0b00000001 -#define GRAPH_DIRECTED 0b00000010 -#define GRAPH_MIXED_DIRECTED 0b00000011 -#define GRAPH_CYCLIC 0b00000000 -#define GRAPH_ACYCLIC 0b00000100 -#define GRAPH_STRICT 0b00001000 -#define GRAPH_NON_NEGATIVE_WEIGHT 0b00010000 -//#define GRAPH_MULTIPLE 0b00010000 - -/** - * Creation and initialization - */ -graph_t* graph_new(char mask, int initial_num_vertices, int SYNC_MODE); - -/** - * Destruction - */ - -int graph_free(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t*); - -int graph_clear(void (*vertex_data_callback) (void* vertex_data), void (*edge_data_callback) (void* edge_data), graph_t*); - -/** - * Vertex Functions - */ -int graph_add_vertex(char* name, void* vertex_data, graph_t*); - -int graph_find_vertex(char* name, graph_t*); // assumes only one ocurrence - -int graph_exists_vertex_s(char* name, graph_t*); -int graph_exists_vertex_i(int id, graph_t*); -//contains?? - -int graph_reachable_vertex(int src, int dst, graph_t*); - -vertex_t* graph_get_vertex_s(char* vertex_name, graph_t * graph_p); -vertex_t* graph_get_vertex_i(int vertex_id, graph_t * graph_p); - -void* graph_get_vertex_data_s(char* name, graph_t*); -void* graph_get_vertex_data_i(int id, graph_t*); -/* -linked_list_t* graph_vertex_neighborhood_s(char* name, graph_t*); -linked_list_t* graph_vertex_neighborhood_i(int id, graph_t*); - -linked_list_t* graph_vertex_neighborhood_out_s(char* name, graph_t*); -linked_list_t* graph_vertex_neighborhood_out_i(int id, graph_t*); - -linked_list_t* graph_vertex_neighborhood_in_s(char* name, graph_t*); -linked_list_t* graph_vertex_neighborhood_in_i(int id, graph_t*); -//adjacent -*/ - -int graph_remove_vertex_s(char* vertex_name, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t*); -int graph_remove_vertex_i(int vertex_id, void (*vertex_data_callback) (void* vertex_data),void (*edge_data_callback) (void* edge_data), graph_t*); - - -/** - * Edge Functions - */ -int graph_add_edge_s(char* src, char* dst, void* edge_data, char edge_type, graph_t*); -int graph_add_edge_i(int src, int dst, void* edge_data, char edge_type, graph_t*); -int graph_add_edge_sw(char* src, char* dst, void* edge_data, char edge_type, float weight, graph_t*); -int graph_add_edge_iw(int src, int dst, void* edge_data, char edge_type, float weight, graph_t*); - -int graph_remove_edge_s(char* src, char* dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t*); -int graph_remove_edge_i(int src, int dst, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t*); -int graph_remove_edge_e(edge_t *edge_p, char edge_type, void (*edge_data_callback) (void* edge_data), graph_t*); - -edge_t* graph_get_edge_s(char* src, char* dst, char edge_type, graph_t*); -edge_t* graph_get_edge_i(int src, int dst, char edge_type, graph_t*); - -/** - * Path Functions - */ -//linked_list_t* graph_path_get(int src, int dst, graph_t*); - -/** - * Others - */ -int graph_print(graph_t*); -int graph_print_dot(char* file_name, graph_t*); -int graph_get_order (graph_t*); // vertex number -int graph_get_size (graph_t*); // edge number - -#endif //_GRAPH_H_ diff --git a/containers/test/SConscript b/containers/test/SConscript index a60ef17..a8aaf94 100644 --- a/containers/test/SConscript +++ b/containers/test/SConscript @@ -13,27 +13,4 @@ check_linked_list = env.Program('linked_list.test', source = ['linked_list_test.c', '%s/containers/linked_list.o' % commons_path ] - ) - - -env2 = Environment(CFLAGS = '-std=c99 -D_XOPEN_SOURCE=600 -D_GNU_SOURCE', - CPPPATH = ['#', commons_path, '/usr/include', '/usr/local/include', commons_path ], - LIBPATH = ['/usr/lib', '/usr/local/lib' ], - LIBS = ['check', 'curl', 'm', 'z', 'rt'] - ) -Import("debug") - -if debug == 1: - env2['CFLAGS'] += ' -O0 -g' -else: - env2['CFLAGS'] += ' -O3' - - -graph_time_test = env2.Program('graph_time_test', - ['graph_time_test.c', - '%s/commons/string_utils.o' % commons_path, - '%s/commons/log.o' % commons_path, - Glob('%s/containers/*.o' % commons_path), - Glob('%s/containers/cprops/*.o' % commons_path) - ] - ) + ) \ No newline at end of file diff --git a/containers/test/graph_test.c b/containers/test/graph_test.c deleted file mode 100644 index 8bbfc7d..0000000 --- a/containers/test/graph_test.c +++ /dev/null @@ -1,242 +0,0 @@ - -#include -#include -#include - -#include "../graph.h" -graph_t *g; -Suite *create_test_suite(void); - -//************************** -// Checked fixtures * -//************************** - - -START_TEST(test_empty_graph) { - - g = graph_new(GRAPH_DIRECTED | GRAPH_CYCLIC, 20, COLLECTION_MODE_ASYNCHRONIZED); - - fail_if( graph_remove_vertex_i(0, NULL, NULL, g) != -1, "Removing inexistent vertex: return should be -1"); - fail_if( graph_remove_edge_i(0, 1, GRAPH_DIRECTED, NULL, g) != -1, "Removing inexistent vertex: return should be -1"); - fail_if( graph_remove_edge_i(0, 0, GRAPH_DIRECTED, NULL, g) != -1, "Removing inexistent vertex: return should be -1"); - - graph_free(NULL, NULL, g); -} -END_TEST - - -START_TEST(test_small_graph) { - - g = graph_new(GRAPH_DIRECTED | GRAPH_ACYCLIC |GRAPH_STRICT, 20, COLLECTION_MODE_ASYNCHRONIZED); - int ret = graph_add_vertex("A", NULL, g); - - fail_if( ret < 0, "add_vertex: return should be the new id but id=%d", ret); - ret = graph_add_vertex("B", NULL, g); - fail_if( ret < 0, "add_vertex: return should be the new id but id=%d", ret); - ret = graph_add_vertex("C", NULL, g); - fail_if( ret < 0, "add_vertex: return should be the new id but id=%d", ret); - - - ret = graph_add_edge_sw("A", "B", NULL, GRAPH_DIRECTED, 2, g); - fail_if( ret != 0, "add_vertex: return should be 0 but ret=%d", ret); - - ret = graph_add_edge_sw("D", "B", NULL, GRAPH_DIRECTED, 2, g); - fail_if( ret != -1, "add_vertex: non existent vertex: return should be -1 but ret=%d", ret); - - ret = graph_add_edge_sw("A", "C", NULL, 9, 2, g); - fail_if( ret != -2, "add_vertex: non supported edge type: return should be -2 but ret=%d", ret); - - ret = graph_add_edge_sw("C", "A", NULL, GRAPH_NON_DIRECTED, 2, g); - fail_if( ret != -3, "add_vertex: non compatible direction type: return should be -3 but ret=%d", ret); - - ret = graph_add_edge_sw("B", "B", NULL, GRAPH_DIRECTED, 2, g); - fail_if( ret != -4, "add_vertex: breaking acyclity: return should be -4 but ret=%d", ret); - - ret = graph_add_edge_sw("A", "B", NULL, GRAPH_DIRECTED, 2, g); - fail_if( ret != -5, "add_vertex: breaking multiplicity: return should be -5 but ret=%d", ret); - - ret = graph_add_edge_sw("C", "B", NULL, GRAPH_DIRECTED, 2, g); - fail_if( ret != 0, "add_vertex: return should be 0 but ret=%d", ret); - - //ret = graph_add_vertex(NULL, NULL, g); - //fail_if( ret < 10, "add_vertex: return should be the new id but id=%d", ret); - - graph_print(g); - - graph_print_dot("check_graph.gv", g); - - graph_free(NULL, NULL, g); -} -END_TEST - - -START_TEST(test_big_graph) { - -} -END_TEST - - -/* ****************************** - * Main entry point * - * ******************************/ - -int main (int argc, char *argv) { - Suite *fs = create_test_suite(); - SRunner *fs_runner = srunner_create(fs); - srunner_run_all(fs_runner, CK_NORMAL); - int number_failed = srunner_ntests_failed (fs_runner); - srunner_free (fs_runner); - return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; -} - - -Suite *create_test_suite(void) { - TCase *tc_create_free = tcase_create("Create and free"); - - //tcase_add_checked_fixture(tc_create_free, create_graph, free_graph); - tcase_add_test(tc_create_free, test_empty_graph); - tcase_add_test(tc_create_free, test_small_graph); - tcase_add_test(tc_create_free, test_big_graph); - //tcase_add_test(tc_create_free, test_create_free); - - //TCase *tc_iterators = tcase_create("Iterators"); - //tcase_add_checked_fixture(tc_iterators, create_graph, free_graph); - //tcase_add_test(tc_iterators, test_iterators); - - // Add test cases to a test suite - Suite *fs = suite_create("Graph"); - suite_add_tcase(fs, tc_create_free); - //suite_add_tcase(fs, tc_iterators); - - return fs; -} - - - - - -/* - - - -#include -#include - -#include "../graph/graph.h" -graph_t *g; -void foo() -{ - - -} - -void free_cond(void* c) -{ - if(c) - free(c); -} - -void* new_mem(const char* c) -{ - return NULL; - char* v = malloc(20); - int i; - for(i = 0; i < 20 && c[i] != 0; i++) - v[i]=c[i]; - v[i] = 0; - return v; -} - -int main() -{ - printf("Holamundo\n"); - - g = graph_new(GRAPH_MIXED_DIRECTED | GRAPH_ACYCLIC, 20, COLLECTION_MODE_ASYNCHRONIZED); - - - graph_add_vertex("A", NULL, g); - graph_add_vertex("B", NULL, g); - graph_add_vertex("C", NULL, g); - graph_add_vertex("D", malloc(29), g); - - graph_add_edge_i(0,1, new_mem("Hola"), GRAPH_DIRECTED,2, g); - graph_add_edge_i(1,2, new_mem("Hola"), GRAPH_DIRECTED,2, g); - void* v = malloc(23); - if(graph_add_edge_i(2,0, v, GRAPH_DIRECTED,2, g)<0) - free(v); - - - graph_print(g); - printf("Clear\n"); - graph_clear(free_cond,free_cond,g); - - graph_add_vertex("A", NULL, g); - graph_add_vertex("S", NULL, g); - graph_add_vertex("D", NULL, g); - graph_add_vertex("F", NULL, g); - graph_add_vertex("G", NULL, g); - - graph_add_edge_s("A","S",NULL,GRAPH_DIRECTED,2,g); - graph_add_edge_s("S","D",NULL,GRAPH_DIRECTED,2,g); - graph_add_edge_s("S","D",NULL,GRAPH_DIRECTED,2,g); - graph_add_edge_s("G","D",NULL,GRAPH_DIRECTED,2,g); - graph_add_edge_s("A","D",NULL,GRAPH_NON_DIRECTED,2,g); - graph_add_edge_s("D","D",NULL,GRAPH_DIRECTED,2,g); - graph_add_edge_s("A","F",NULL,GRAPH_NON_DIRECTED,2,g); - - - graph_add_edge_s("F","G",new_mem("Pepe"),GRAPH_DIRECTED,2,g); - graph_add_edge_s("F","G",new_mem("Pepon"),GRAPH_DIRECTED,2,g); - graph_add_edge_s("F","G",new_mem("Null"),GRAPH_DIRECTED,2,g); - - - graph_add_edge_s("G","S",NULL,GRAPH_NON_DIRECTED,9,g); - graph_add_edge_s("F","S",NULL,GRAPH_DIRECTED,2,g); - - edge_t * e = graph_get_edge_i(3,4,GRAPH_DIRECTED,g); - if(e != NULL) - printf("Edge Tomado %s\n",(char*)e->data); - graph_remove_edge_e(e,GRAPH_DIRECTED,free_cond,g); - graph_remove_edge_s("A","S",GRAPH_DIRECTED,free_cond,g); - graph_remove_edge_s("A","Sasdfasd",GRAPH_DIRECTED,free_cond,g); - graph_remove_edge_s("A","G",GRAPH_DIRECTED,free_cond,g); - //printf("Edge Eliminado\n"); - - - //graph_print(g); - //printf("Go go to Eliminar vertice\n"); - //graph_remove_vertex_s("A",NULL,free_cond,g); - - //graph_add_vertex("GAUSON", NULL, g); -/* linked_list_iterator_t *iter = linked_list_iterator_new(l); - char* c = (char*)linked_list_iterator_curr(iter); - while(c != NULL) - { - printf("CHAR DEL LINKED : %s\n",c); - c = (char*)linked_list_iterator_next(iter); - - } - linked_list_iterator_free(iter); - linked_list_free(l, NULL); - */ - /* - graph_add_edge_s("GAUSON", "F", NULL, GRAPH_NON_DIRECTED,3.1415, g); - graph_add_edge_s("GAUSON", "F", NULL, GRAPH_DIRECTED,2, g); - graph_add_edge_s("F", "GAUSON", NULL, GRAPH_DIRECTED,1.618, g); - - - //graph_remove_vertex_s("dsfg",NULL,free_cond,g); - //graph_remove_vertex_s("S",NULL,free_cond,g); - - graph_print(g); - - graph_print_dot("grafo.gv",g); - - //printf("Existe camino entre 0 y 3? %d\n", graph_path_exists(0,3,g)); - - graph_free(NULL,free_cond,g); - - return 0; -} - -*/ diff --git a/containers/test/graph_time_test.c b/containers/test/graph_time_test.c deleted file mode 100644 index d53f91d..0000000 --- a/containers/test/graph_time_test.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -//#include -#include "../graph.h" - -void stop_crono(char* mensaje, struct timespec * ini_time) -{ - struct timespec timedif, fin_time; - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &fin_time);//----------------------- - timedif.tv_sec = fin_time.tv_sec - ini_time->tv_sec; - timedif.tv_nsec = fin_time.tv_nsec - ini_time->tv_nsec; - if (timedif.tv_nsec < 0) - { - timedif.tv_nsec += 1000000000; - timedif.tv_sec--; - } - printf(mensaje, (int)timedif.tv_sec, timedif.tv_nsec); -} - -int main (void) -{ - struct timespec ini_time; - - graph_t *g; - int num_vertices = 1000000; - int num_edges = 10000000; - int name_length = 255; - char ** names; - int i; - - srand(time(NULL)); - - names = (char**) malloc (sizeof(char*)*num_vertices); - - for (i = 0; i < num_vertices; i++) - { - //itoa(i, names[i], 10); - names[i] = (char*) malloc (sizeof(char)*name_length); - sprintf(names[i], "%d", i); - //printf ("name[%d] = %s\n", i, names[i]); - } - - printf("grafo con %d nodos\n", num_vertices); - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++++ - - g = graph_new (GRAPH_CYCLIC | GRAPH_DIRECTED, num_vertices, COLLECTION_MODE_ASYNCHRONIZED); - - stop_crono("tiempo en crear el grafo: t = %d s y %ld ns\n", &ini_time);//----------------------- - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//++++++++++++++++++++++++++++++++++ - - for (i = 0; i < num_vertices; i++) - graph_add_vertex (names[i], NULL, g); - - stop_crono("tiempo rellenar vertices aleatorios: t = %d s y %ld ns\n", &ini_time);//----------------------- - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++ - - for (i = 0; i < num_edges; i++) - graph_add_edge_iw(rand()%num_vertices, rand()%num_vertices, NULL, GRAPH_DIRECTED, 1, g); - - stop_crono("tiempo en relenar edges aleatorios = %d s y %ld ns\n", &ini_time);//----------------- - - printf("solo cumplian las condiciones %d edges\n", g->num_edges); - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++++ - - graph_print_dot("grafo_tiempo.gv", g); - - stop_crono("tiempo en print dot: t = %d s y %ld ns\n", &ini_time);//----------------------- - - - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ini_time);//+++++++++++++++++++++++++++++++++++ - - graph_free(NULL, NULL, g); - - stop_crono("tiempo en liberar grafo: t = %d s y %ld ns\n", &ini_time);//----------------------- - - for (i = 0; i < num_vertices; i++) - free(names[i]); - - free (names); - - printf("\n"); - return 0; -}