From e4772c217f27b7bbefda654514b49f871b08b62c Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 26 Nov 2024 15:10:30 +0100 Subject: [PATCH 1/3] More efficient memory cleanup --- README.md | 10 +- radius_clustering/utils/main-emos.c | 106 +++++--------- radius_clustering/utils/mds3-util.h | 214 ++-------------------------- 3 files changed, 54 insertions(+), 276 deletions(-) diff --git a/README.md b/README.md index 44175da..6ab52e7 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ You can install Radius Clustering using pip: pip install radius-clustering ``` -> Note: This package is not yet available on PyPI. You may need to install it from the source. +> Note: This package is not yet available on PyPI. You may need to install it from the source. See [the documentation](https://lias-laboratory.github.io/radius_clustering/installation.html) for more details. ## Usage @@ -53,7 +53,11 @@ print(labels) ## Documentation -To build the documentation, you can run the following command, assuming you have Sphinx installed: +You can find the full documentation for Radius Clustering [here](https://lias-laboratory.github.io/radius_clustering/). + +### Building the documentation + +To build the documentation, you can run the following command, assuming you have all dependencies needed installed: ```bash cd docs @@ -73,7 +77,7 @@ If you want to know more about the experiments conducted with the package, pleas ## Contributing -Contributions to MDS Clustering are welcome! Please feel free to submit a Pull Request. +Contributions to Radius Clustering are welcome! Please feel free to submit a Pull Request. ## License diff --git a/radius_clustering/utils/main-emos.c b/radius_clustering/utils/main-emos.c index 6d25215..b35a117 100644 --- a/radius_clustering/utils/main-emos.c +++ b/radius_clustering/utils/main-emos.c @@ -179,7 +179,6 @@ two vertices adj iif: */ static inline int is_2_adj(int marked_node,int test_node){ - int adj=0, comneibor=0; for_each_neighbor(test_node,neibor){ if(neibor==marked_node){ if(!(branched(test_node) && branched(marked_node))) @@ -522,7 +521,6 @@ static int partition_free_vertices(){ } static inline void clear_iset(int isetno,int insert_node){ - int marked_count=0; int involved=involved(insert_node); USED(TMP_STK)=0; for_each_vec_item(iSET[isetno],int,it){ @@ -558,7 +556,6 @@ static inline void clear_iset(int isetno,int insert_node){ static int improve_partition(int maxlb,int target){ for(int i=SUB_PROBLEM_SIZE-1;i>=CUR_UND_IDX;i--){ int node=CFG[i]; - int inserted=0; set_marked_status(node); for_each_neighbor(node,neibor){ @@ -622,7 +619,6 @@ static int repartition_vertices(int maxlb){ set_marked_status(neibor); } - int inserted=0; for(int j=isno(node)+1;jmax_count) @@ -1370,16 +1366,6 @@ void solve_subproblems(){ }while(ptr>> %s |V| %d |E| %d FIXED %d INIT %d BEST %d TREE %llu TIME(s) %0.2lf\n",inst,NB_NODE,NB_EDGE,NB_FIXED,INIT_UPPER_BOUND,USED(VEC_SOLUTION),NB_TREE, get_utime()); -} - // Define global variables extern unsigned long long total_branches = 0; extern unsigned long long pruned_branches = 0; @@ -1501,6 +1487,43 @@ void check_consistance(){ void cleanup(){ + + // Free all allocated memory + if (CFG != NULL) { + free(CFG); + CFG = NULL; + } + if (LOC != NULL) { + free(LOC); + LOC = NULL; + } + if (STATUS != NULL) { + free(STATUS); + STATUS = NULL; + } + if (PID != NULL) { + free(PID); + PID = NULL; + } + free_stack(BRA_STK); + free_stack(FIX_STK); + free_stack(TMP_STK); + free_stack(ADJ_STK); + free_stack(VEC_SOLUTION); + free_stack(VEC_SUBGRAPHS); + + for (int i = 0; i <= MAXIS; i++) { + free_stack(iSET[i]); + } + + if (ADJIDX != NULL) { + free(ADJIDX); + ADJIDX = NULL; + } + + + + free_block(); // Reset all global variables BLOCK_COUNT = 0; NB_NODE = 0; @@ -1529,59 +1552,6 @@ void cleanup(){ CUT_OFF = 0; BEST_SOL_TIME = 0; instance[0] = '\0'; - - // Free all allocated memory - if (CFG != NULL) { - free(CFG); - CFG = NULL; - } - if (LOC != NULL) { - free(LOC); - LOC = NULL; - } - if (STATUS != NULL) { - free(STATUS); - STATUS = NULL; - } - if (PID != NULL) { - free(PID); - PID = NULL; - } - if (BRA_STK != NULL) { - free(BRA_STK); - BRA_STK = NULL; - } - if (FIX_STK != NULL) { - free(FIX_STK); - FIX_STK = NULL; - } - if (TMP_STK != NULL) { - free(TMP_STK); - TMP_STK = NULL; - } - if (ADJ_STK != NULL) { - free(ADJ_STK); - ADJ_STK = NULL; - } - if (ADJIDX != NULL) { - free(ADJIDX); - ADJIDX = NULL; - } - if (VEC_SOLUTION != NULL) { - free(VEC_SOLUTION); - VEC_SOLUTION = NULL; - } - if (VEC_SUBGRAPHS != NULL) { - free(VEC_SUBGRAPHS); - VEC_SUBGRAPHS = NULL; - } - - for (int i = 0; i <= MAXIS; i++) { - if (iSET[i] != NULL) { - free(iSET[i]); - iSET[i] = NULL; - } - } } void handler(int sig) { diff --git a/radius_clustering/utils/mds3-util.h b/radius_clustering/utils/mds3-util.h index 1ef75e6..fc6fab2 100644 --- a/radius_clustering/utils/mds3-util.h +++ b/radius_clustering/utils/mds3-util.h @@ -112,6 +112,14 @@ assert((Vec)->addr); \ (Vec)->used=0;\ }while(0) +#define free_stack(Vec) \ +do{ \ +if(Vec!=NULL){\ +free(Vec->addr);\ +free(Vec);\ +}\ +}while(0) + #define for_each_vec_item(Vec,T,It) for(T *It=Vec->addr, *__end=Vec->addr+Vec->used;It != __end;It++) #define remove_value_from_vector(Vec,T,Val) do{ \ @@ -221,13 +229,7 @@ static VEC_INT * FIX_STK,* TMP_STK; static VEC_INT * VEC_SUBGRAPHS; static VEC_INT * VEC_SOLUTION; static int NB_FIXED=0,NEW_IDX=0,NB_UNFIXED=0; -static void parse_parmerters(int argc, char *argv[]) { - printf("# searching on instance %s ...\n", argv[1]); - if (argc > 2) { - sscanf(argv[2], "%d", &INIT_UPPER_BOUND); - printf("# specify the initial upper bound %d \n", INIT_UPPER_BOUND); - } -} + static void allcoate_memory_for_adjacency_list(int nb_node, int nb_edge,int offset) { int i, block_size = 40960000, free_size = 0; @@ -255,67 +257,6 @@ static void allcoate_memory_for_adjacency_list(int nb_node, int nb_edge,int offs } } -static int _read_graph_from_adjacency_matrix(int** adj_matrix, int num_nodes) { - int j, l_node, r_node, nb_edge = 0, max_node = num_nodes, offset = 1; - - // Init Node_Degree - memset(Node_Degree, 0, (max_node + 1) * sizeof(int)); - // Count edges and degrees - - for (l_node = 0; l_node < max_node; l_node++){ - for (r_node = 0; r_node < l_node; r_node++){ - if (adj_matrix[l_node][r_node] == 1) { - nb_edge++; - Node_Degree[l_node]++; - Node_Degree[r_node]++; - } - } - } - - - NB_NODE = max_node; - - // Allocate memory for Node_Neibors - - Node_Neibors = (int **)malloc((NB_NODE + 1)*sizeof(int *)); - - allcoate_memory_for_adjacency_list(NB_NODE, nb_edge, 1); - - nb_edge = 0; - // Reset Node_Degree to use as a counter - memset(Node_Degree, 0, (NB_NODE + 1)* sizeof(int)); - // Fill Node_Neibors - for (l_node = 1; l_node <= NB_NODE; l_node++){ - for (r_node = 1; r_node < l_node; r_node++){ - if (adj_matrix[l_node - 1][r_node - 1] == 1) { - for (j = 0; j < Node_Degree[l_node]; j++) { - if (Node_Neibors[l_node][j] == r_node) { - break; - } - } - if (j == Node_Degree[l_node]) { - Node_Neibors[l_node][Node_Degree[l_node]] = r_node; - Node_Neibors[r_node][Node_Degree[r_node]] = l_node; - Node_Degree[l_node]++; - Node_Degree[r_node]++; - nb_edge++; - } - } - - } - } - NB_EDGE = nb_edge; - Max_Degree = 0; - for_each_vertex(node) { - Node_Neibors[node][Node_Degree[node]] = NONE; - if (Node_Degree[node] > Max_Degree) { - Max_Degree = Node_Degree[node]; - Max_Degree_Node = node; - } - } - - return TRUE; -} static int _read_graph_from_edge_list(int* edges, int n, int nb_edges) { int i, j, l_node, r_node, nb_edge = 0, max_node = n, offset = 0; @@ -380,135 +321,6 @@ static int _read_graph_from_edge_list(int* edges, int n, int nb_edges) { } return TRUE; } - -static int _read_graph_from_file(char *input_file, int format) { - int j, l_node, r_node, nb_edge = 0, max_node = NONE, offset = 0; - int node = 1; - char line[128], word[10]; - FILE* fp_in = fopen(input_file, "r"); - - if (fp_in == NULL ) { - printf("Error: fail to open file %s\n", input_file); - return FALSE; - } - - if (format == 1) - printf("R reading file in format of with "); - else - printf("R reading file in format of with "); - - memset(Node_Degree, 0, MAX_NODE*sizeof(int)); - - while (fgets(line, 127, fp_in) != NULL ) { - if ((format == 1 && line[0] == 'e') - || (format == 2 && line[0] != '%')) { - if (format == 1) - sscanf(line, "%s%d%d", word, &l_node, &r_node); - else - sscanf(line, "%d%d", &l_node, &r_node); - if (l_node >= 0 && r_node >= 0 && l_node != r_node) { - - nb_edge++; - - if (l_node > max_node) - max_node = l_node; - if (r_node > max_node) - max_node = r_node; - - if (offset ==0 && (l_node == 0 || r_node == 0)){ - offset = 1; - } - - if (max_node+offset>=MAX_NODE) { - printf("! The graph goes beyond the maximum size (%d) can be processed.\n",MAX_NODE); - printf("! Please modify the definition of the variable MAX_NODE to fit the size.\n"); - exit(1); - } - - Node_Degree[l_node]++; - Node_Degree[r_node]++; - - } - } - } - NB_NODE = max_node; - NB_NODE = NB_NODE + offset; - - Node_Neibors = (int **) malloc((NB_NODE + 1) * sizeof(int *)); - allcoate_memory_for_adjacency_list(NB_NODE, nb_edge, 1); - memset(Node_Degree, 0, (NB_NODE + 1) * sizeof(int)); - - nb_edge = 0; - fseek(fp_in, 0L, SEEK_SET); - while (fgets(line, 127, fp_in) != NULL ) { - if ((format == 1 && line[0] == 'e') - || (format == 2 && line[0] != '%')) { - if (format == 1) - sscanf(line, "%s%d%d", word, &l_node, &r_node); - else - sscanf(line, "%d%d", &l_node, &r_node); - if (l_node >= 0 && r_node >= 0 && l_node != r_node) { - if(offset){ - l_node +=offset; - r_node +=offset; - } - for (j = 0; j < Node_Degree[l_node]; j++) { - if (Node_Neibors[l_node][j] == r_node) - break; - } - if (j == Node_Degree[l_node]) { - Node_Neibors[l_node][Node_Degree[l_node]] = r_node; - Node_Neibors[r_node][Node_Degree[r_node]] = l_node; - Node_Degree[l_node]++; - Node_Degree[r_node]++; - nb_edge++; - } - } - } - } - - NB_EDGE = nb_edge; - Max_Degree = 0; - for (node = 1; node <= NB_NODE; node++) { - Node_Neibors[node][Node_Degree[node]] = NONE; - if (Node_Degree[node] > Max_Degree){ - Max_Degree = Node_Degree[node]; - Max_Degree_Node=node; - } - } - //printf("Max Node=%d\n",Max_Degree_Node); - //UPPER_BOUND=Max_Degree+PARA.KX; - return TRUE; -} - - -static int read_instance(char *input_file) { - const char * fileStyle="clq"; - if(strrchr(input_file, '.')!=NULL) - fileStyle = strrchr(input_file, '.') + 1; - - if (strcmp(fileStyle, "clq") == 0) { - _read_graph_from_file(input_file, 1); - } else if (strcmp(fileStyle, "edges") == 0) { - _read_graph_from_file(input_file, 2); - } else if (strcmp(fileStyle, "mtx") == 0) { - _read_graph_from_file(input_file, 2); - } else if (FORMAT == 1) { - _read_graph_from_file(input_file, 1); - } else if (FORMAT == 2) { - _read_graph_from_file(input_file, 2); - } else { - _read_graph_from_file(input_file, 1); - } - - NB_NODE_O = NB_NODE; - NB_EDGE_O = NB_EDGE; - D0 = ((float) NB_EDGE * 2 / NB_NODE / (NB_NODE - 1)); - - READ_TIME = get_utime(); - fflush(stdout); - return TRUE; -} static void free_block() { int i = 0; @@ -516,14 +328,6 @@ static void free_block() { free(BLOCK_LIST[i]); } -static char * getInstanceName(char *s) { - if (strrchr(s, '/') == NULL ) - return s; - else - return strrchr(s, '/') + 1; -} - - static int *dfn,*low,*TarStack,TarTop,CNT=0,*SonNum,*RecSta,RecTop,*LasSon,*LasNodeIndex; //After preprocess, following variables might still be useful: From ba65745ae144a1aa4cfa7e8549d9edd159dcadfa Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 20 Dec 2024 10:32:55 +0100 Subject: [PATCH 2/3] updated version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c3374dc..480d149 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "radius-clustering" -version = "1.0.0" +version = "1.0.1" description = "A Clustering under radius constraints algorithm using minimum dominating sets" readme = "README.md" authors = [ From 97bd70c0f8302feb0826bd18ed7671b96bbae3be Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 20 Dec 2024 18:43:56 +0100 Subject: [PATCH 3/3] Preparing for new minor version 1.1 with better memory efficiency and better usage of uint32 --- README.md | 2 -- pyproject.toml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 6ab52e7..b389e50 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,6 @@ You can install Radius Clustering using pip: pip install radius-clustering ``` -> Note: This package is not yet available on PyPI. You may need to install it from the source. See [the documentation](https://lias-laboratory.github.io/radius_clustering/installation.html) for more details. - ## Usage Here's a basic example of how to use Radius Clustering: diff --git a/pyproject.toml b/pyproject.toml index a207a50..7dd0a63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "radius-clustering" -version = "1.0.1" +version = "1.1.0" description = "A Clustering under radius constraints algorithm using minimum dominating sets" readme = "README.md" authors = [