diff --git a/src/branch_and_cut.c b/src/branch_and_cut.c index 4f8cd0e..33890cc 100644 --- a/src/branch_and_cut.c +++ b/src/branch_and_cut.c @@ -99,6 +99,8 @@ static int BNC_solve_node(struct BNC *bnc, int depth) rval = LP_get_obj_val(lp, &objval); abort_if(rval, "LP_get_obj_val failed\n"); + if(depth == 1) ROOT_VALUE = objval; + if (ceil(objval) > *best_val + LP_EPSILON) { log_debug("Branch pruned by bound (%.2lf > %.2lf).\n", objval, @@ -124,6 +126,8 @@ static int BNC_solve_node(struct BNC *bnc, int depth) rval = LP_get_obj_val(lp, &objval); abort_if(rval, "LP_get_obj_val failed"); + if(depth == 1) ROOT_VALUE = objval; + if (ceil(objval) > *best_val + LP_EPSILON) { log_debug("Branch pruned by bound (%.2lf > %.2lf).\n", objval, diff --git a/src/flow.c b/src/flow.c index 0faf6e4..ac802de 100644 --- a/src/flow.c +++ b/src/flow.c @@ -54,8 +54,6 @@ int flow_mark_reachable_nodes( return rval; } -extern double FLOW_CPU_TIME; - int flow_find_max_flow( const struct Graph *digraph, const double *capacities, @@ -67,7 +65,6 @@ int flow_find_max_flow( int rval = 0; FLOW_MAX_FLOW_COUNT++; - double initial_time = get_current_time(); for (int i = 0; i < digraph->node_count; i++) digraph->nodes[i].mark = 0; @@ -157,8 +154,6 @@ int flow_find_max_flow( rval = flow_mark_reachable_nodes(digraph, residual_caps, from); abort_if(rval, "flow_mark_reachable_nodes failed"); - FLOW_CPU_TIME += get_current_time() - initial_time; - CLEANUP: if (path_edges) free(path_edges); if (residual_caps) free(residual_caps); diff --git a/src/flow.h b/src/flow.h index 895c709..f3a9595 100644 --- a/src/flow.h +++ b/src/flow.h @@ -25,8 +25,6 @@ int flow_mark_reachable_nodes( int flow_main(int argc, char **argv); -extern int FLOW_MAX_FLOW_COUNT; - #include "graph.h" #endif //_PROJECT_FLOW_H_ diff --git a/src/gtsp-comb.c b/src/gtsp-comb.c index 24a7d99..3d00dfa 100644 --- a/src/gtsp-comb.c +++ b/src/gtsp-comb.c @@ -206,11 +206,11 @@ int find_components( log_verbose("Components:\n"); for (int i = 0; i < graph->node_count; i++) - log_verbose(" %d %d\n", i, components[i]); + log_verbose(" %d %d\n", i, components[i]); log_verbose("Component sizes:\n"); for (int i = 0; i < graph->node_count; i++) - log_verbose(" %d %d\n", i, component_sizes[i]); + log_verbose(" %d %d\n", i, component_sizes[i]); CLEANUP: if (stack) free(stack); @@ -370,6 +370,7 @@ static int shrink_clusters( int find_comb_cuts(struct LP *lp, struct GTSP *data) { int rval = 0; + double initial_time = get_current_time(); double *x = 0; double *shrunken_x = 0; @@ -414,9 +415,7 @@ int find_comb_cuts(struct LP *lp, struct GTSP *data) component_sizes); abort_if(rval, "find_components failed"); -#if LOG_LEVEL >= LOG_LEVEL_DEBUG int original_cut_pool_size = lp->cut_pool_size; -#endif for (int i = 0; i < cluster_count; i++) { @@ -447,7 +446,11 @@ int find_comb_cuts(struct LP *lp, struct GTSP *data) abort_if(rval, "add_comb_cut failed"); } - log_debug(" %d combs\n", lp->cut_pool_size - original_cut_pool_size); + int added_cuts_count = lp->cut_pool_size - original_cut_pool_size; + log_debug(" %d combs\n", added_cuts_count); + + COMBS_TIME += get_current_time() - initial_time; + COMBS_COUNT += added_cuts_count; CLEANUP: graph_free(&shrunken_graph); diff --git a/src/gtsp-subtour.c b/src/gtsp-subtour.c index 8de13cb..5a8ba3f 100644 --- a/src/gtsp-subtour.c +++ b/src/gtsp-subtour.c @@ -4,7 +4,7 @@ #include "util.h" #include "flow.h" -extern double FLOW_CPU_TIME; +extern double SUBTOUR_TIME; int static build_flow_digraph( struct GTSP *data, double *x, struct Graph *digraph, double *capacities) @@ -178,6 +178,7 @@ int find_exact_subtour_cuts( double *x = 0; double *capacities = 0; + double initial_time = get_current_time(); int added_cuts_count = 0; struct Graph *graph = data->graph; @@ -214,6 +215,7 @@ int find_exact_subtour_cuts( added_cuts_count = lp->cut_pool_size - original_cut_pool_size; log_debug(" %d cluster-to-cluster\n", added_cuts_count); + SUBTOUR_CLUSTER_CLUSTER_COUNT += added_cuts_count; if (added_cuts_count > 0) goto CLEANUP; @@ -225,6 +227,7 @@ int find_exact_subtour_cuts( added_cuts_count = lp->cut_pool_size - original_cut_pool_size; log_debug(" %d node-to-cluster\n", added_cuts_count); + SUBTOUR_NODE_CLUSTER_COUNT += added_cuts_count; if (added_cuts_count > 0) goto CLEANUP; @@ -236,9 +239,12 @@ int find_exact_subtour_cuts( added_cuts_count = lp->cut_pool_size - original_cut_pool_size; log_debug(" %d node-to-node\n", added_cuts_count); + SUBTOUR_NODE_NODE_COUNT += added_cuts_count; if (added_cuts_count > 0) goto CLEANUP; + SUBTOUR_TIME += get_current_time() - initial_time; + CLEANUP: graph_free(&digraph); if (capacities) free(capacities); diff --git a/src/gtsp.c b/src/gtsp.c index f55c0fd..c8c89e4 100644 --- a/src/gtsp.c +++ b/src/gtsp.c @@ -3,10 +3,10 @@ #include #include #include +#include #include "gtsp.h" #include "geometry.h" #include "util.h" -#include "flow.h" #include "gtsp-subtour.h" #include "gtsp-comb.h" @@ -618,11 +618,6 @@ static int GTSP_parse_args(int argc, char **argv) return rval; } -double FLOW_CPU_TIME = 0; -double LP_SOLVE_TIME = 0; -double LP_CUT_POOL_TIME = 0; -int LP_OPTIMIZE_COUNT = 0; - int GTSP_main(int argc, char **argv) { int rval = 0; @@ -631,8 +626,9 @@ int GTSP_main(int argc, char **argv) struct GTSP data; double *initial_x = 0; + double initial_time = get_current_time(); - SEED = (unsigned int) get_real_time() % 1000000; + SEED = (unsigned int) get_real_time() % 1000; rval = GTSP_init_data(&data); abort_if(rval, "GTSP_init_data failed"); @@ -651,25 +647,29 @@ int GTSP_main(int argc, char **argv) log_info(" input_cluster_count = %d\n", input_cluster_count); log_info(" grid_size = %d\n", grid_size); + char instance_name[1000]; + sprintf(instance_name, "gtsp-m%d-n%d-s%d", input_cluster_count, + input_node_count, SEED); + rval = GTSP_create_random_problem(input_node_count, input_cluster_count, grid_size, &data); abort_if(rval, "GTSP_create_random_problem failed"); char filename[100]; - sprintf(filename, "input/gtsp-m%d-n%d-s%d.in", input_cluster_count, - input_node_count, SEED); + sprintf(filename, "input/%s.in", instance_name); log_info("Writing random instance to file %s\n", filename); rval = GTSP_write_problem(&data, filename); abort_if(rval, "GTSP_write_problem failed"); - #if LOG_LEVEL >= LOG_LEVEL_DEBUG +#if LOG_LEVEL >= LOG_LEVEL_DEBUG log_info("Writing random instance to file gtsp.in\n"); rval = GTSP_write_problem(&data, "gtsp.in"); #endif int init_val; - initial_x = (double*) malloc((data.graph->node_count + data.graph->edge_count) * sizeof(double)); + initial_x = (double *) malloc( + (data.graph->node_count + data.graph->edge_count) * sizeof(double)); abort_if(!initial_x, "could not allocate initial_x"); rval = inital_tour_value(&data, &init_val, initial_x); @@ -684,15 +684,14 @@ int GTSP_main(int argc, char **argv) bnc.problem_init_lp = (int (*)(struct LP *, void *)) GTSP_init_lp; bnc.problem_add_cutting_planes = (int (*)( struct LP *, void *)) GTSP_add_cutting_planes; - bnc.problem_solution_found = (int (*)(struct BNC*, - void *, double *)) GTSP_solution_found; + bnc.problem_solution_found = (int (*)( + struct BNC *, void *, double *)) GTSP_solution_found; double opt_val = 0.0; if (strlen(input_x_filename) == 0) { - sprintf(input_x_filename, "optimal/gtsp-m%d-n%d-s%d.out", - input_cluster_count, input_node_count, SEED); + sprintf(input_x_filename, "optimal/%s.out", instance_name); FILE *file = fopen(input_x_filename, "r"); @@ -742,12 +741,64 @@ int GTSP_main(int argc, char **argv) opt_val); } + TOTAL_TIME = get_current_time() - initial_time; + log_info("Branch-and-bound nodes: %d\n", BNC_NODE_COUNT); - log_info("Max-flow calls: %d\n", FLOW_MAX_FLOW_COUNT); - log_info("Max-flow computation time: %.2lf\n", FLOW_CPU_TIME); - log_info("LP optimize calls: %d\n", LP_OPTIMIZE_COUNT); + log_info("LP optimize calls: %d\n", LP_SOLVE_COUNT); log_info("LP solving time: %.2lf\n", LP_SOLVE_TIME); - log_info("LP cut pool management time: %.2lf\n", LP_CUT_POOL_TIME); + log_info("LP cut pool management time: %.2lf\n", CUT_POOL_TIME); + + FILE *file = fopen("stats.tab", "a"); + abort_if(!file, "could not open stats.tab"); + + + struct stat st; + stat("stats.tab", &st); + + if(st.st_size == 0) + { + fprintf(file, "%-20s ", "instance"); + fprintf(file, "%-8s ", "time"); + fprintf(file, "%-8s ", "subt-t"); + fprintf(file, "%-8s ", "combs-t"); + fprintf(file, "%-8s ", "pool-t"); + fprintf(file, "%-8s ", "pool-m"); + fprintf(file, "%-8s ", "lp-count"); + fprintf(file, "%-8s ", "lp-time"); + fprintf(file, "%-8s ", "lp-rows"); + fprintf(file, "%-8s ", "lp-cols"); + fprintf(file, "%-8s ", "init-v"); + fprintf(file, "%-8s ", "opt-v"); + fprintf(file, "%-8s ", "root-v"); + fprintf(file, "%-8s ", "nodes"); + fprintf(file, "%-8s ", "subt-cc"); + fprintf(file, "%-8s ", "subt-nc"); + fprintf(file, "%-8s ", "subt-nn"); + fprintf(file, "%-8s ", "combs"); + + fprintf(file, "\n"); + } + + fprintf(file, "%-20s ", instance_name); + fprintf(file, "%-8.2lf ", TOTAL_TIME); + fprintf(file, "%-8.2lf ", SUBTOUR_TIME); + fprintf(file, "%-8.2lf ", COMBS_TIME); + fprintf(file, "%-8.2lf ", CUT_POOL_TIME); + fprintf(file, "%-8ld ", CUT_POOL_MAX_MEMORY/1024/1024); + fprintf(file, "%-8d ", LP_SOLVE_COUNT); + fprintf(file, "%-8.2lf ", LP_SOLVE_TIME); + fprintf(file, "%-8d ", LP_MAX_ROWS); + fprintf(file, "%-8d ", LP_MAX_COLS); + fprintf(file, "%-8d ", init_val); + fprintf(file, "%-8.0lf ", bnc.best_obj_val); + fprintf(file, "%-8.0lf ", ROOT_VALUE); + fprintf(file, "%-8d ", BNC_NODE_COUNT); + fprintf(file, "%-8d ", SUBTOUR_CLUSTER_CLUSTER_COUNT); + fprintf(file, "%-8d ", SUBTOUR_NODE_CLUSTER_COUNT); + fprintf(file, "%-8d ", SUBTOUR_NODE_NODE_COUNT); + fprintf(file, "%-8d ", COMBS_COUNT); + fprintf(file, "\n"); + fclose(file); CLEANUP: if (OPTIMAL_X) free(OPTIMAL_X); diff --git a/src/gtsp.h b/src/gtsp.h index d138a78..f69f94d 100644 --- a/src/gtsp.h +++ b/src/gtsp.h @@ -62,7 +62,5 @@ int list_length(struct Tour * tour, struct GTSP* data); void print_list(struct Tour * tour, struct GTSP* data); -extern double *OPTIMAL_X; -extern double FLOW_CPU_TIME; #endif //_PROJECT_GTSP_H_ diff --git a/src/lp.c b/src/lp.c index 5660120..df4b65c 100644 --- a/src/lp.c +++ b/src/lp.c @@ -5,6 +5,7 @@ #include #include "lp.h" #include "util.h" +#include "main.h" int LP_open(struct LP *lp) { @@ -158,9 +159,9 @@ int LP_change_bound(struct LP *lp, int col, char lower_or_upper, double bnd) return rval; } -extern int LP_OPTIMIZE_COUNT; +extern int LP_SOLVE_COUNT; extern double LP_SOLVE_TIME; -extern double LP_CUT_POOL_TIME; +extern double CUT_POOL_TIME; int LP_update_cut_ages(struct LP *lp) { @@ -196,26 +197,30 @@ int LP_update_cut_ages(struct LP *lp) return rval; } + + int LP_optimize(struct LP *lp, int *infeasible) { - LP_OPTIMIZE_COUNT++; + LP_SOLVE_COUNT++; int rval = 0, solstat; *infeasible = 0; -#if LOG_LEVEL >= LOG_LEVEL_DEBUG int numrows = CPXgetnumrows(lp->cplex_env, lp->cplex_lp); int numcols = CPXgetnumcols(lp->cplex_env, lp->cplex_lp); + + if(numrows > LP_MAX_ROWS) LP_MAX_ROWS = numrows; + if(numrows > LP_MAX_COLS) LP_MAX_COLS = numcols; + log_debug("Optimizing LP (%d rows %d cols)...\n", numrows, numcols); -#endif - double time_before = get_current_time(); + double initial_time = get_current_time(); + rval = CPXdualopt(lp->cplex_env, lp->cplex_lp); abort_if(rval, "CPXdualopt failed"); - double time_after = get_current_time(); - LP_SOLVE_TIME += time_after - time_before; + LP_SOLVE_TIME += get_current_time() - initial_time; solstat = CPXgetstat(lp->cplex_env, lp->cplex_lp); if (solstat == CPX_STAT_INFEASIBLE) @@ -234,9 +239,9 @@ int LP_optimize(struct LP *lp, int *infeasible) abort_if(rval, "LP_get_obj_val failed"); log_debug(" obj val = %.4lf\n", objval); - log_debug(" time = %.4lf\n", time_after - time_before); + log_debug(" time = %.4lf\n", get_current_time() - initial_time); - time_before = get_current_time(); + initial_time = get_current_time(); rval = LP_update_cut_ages(lp); abort_if(rval, "LP_update_cut_ages failed"); @@ -244,8 +249,7 @@ int LP_optimize(struct LP *lp, int *infeasible) rval = LP_remove_old_cuts(lp); abort_if(rval, "LP_remove_old_cuts failed"); - time_after = get_current_time(); - LP_CUT_POOL_TIME += time_after - time_before; + CUT_POOL_TIME += get_current_time() - initial_time; CLEANUP: return rval; @@ -352,6 +356,9 @@ int LP_remove_old_cuts(struct LP *lp) log_debug(" %ld cuts (%ld nz, %ld MiB)\n", lp->cut_pool_size, nz, size/1024/1024); + if(size > CUT_POOL_MAX_MEMORY) + CUT_POOL_MAX_MEMORY = size; + CLEANUP: if (should_remove) free(should_remove); return rval; @@ -426,8 +433,8 @@ int compare_cuts(struct Row *cut1, struct Row *cut2) int LP_add_cut(struct LP *lp, struct Row *cut) { int rval = 0; + double initial_time = get_current_time(); - double time_before = get_current_time(); rval = LP_update_hash(cut); abort_if(rval, "LP_update_hash failed"); @@ -458,9 +465,7 @@ int LP_add_cut(struct LP *lp, struct Row *cut) cut->cplex_row_index = CPXgetnumrows(lp->cplex_env, lp->cplex_lp) - 1; cut->age = 0; - double time_after = get_current_time(); - LP_CUT_POOL_TIME += time_after - time_before; - + CUT_POOL_TIME += get_current_time() - initial_time; CLEANUP: return rval; } diff --git a/src/main.c b/src/main.c index 0bbfef2..06bc73f 100644 --- a/src/main.c +++ b/src/main.c @@ -10,6 +10,27 @@ int GEOMETRIC_DATA = 0; int NODE_COUNT_RAND = 0; int GRID_SIZE_RAND = 100; +double SUBTOUR_TIME = 0; +double COMBS_TIME = 0; + +double CUT_POOL_TIME = 0; +long CUT_POOL_MAX_MEMORY = 0; + +double LP_SOLVE_TIME = 0; + +int LP_MAX_COLS = 0; +int LP_MAX_ROWS = 0; +int LP_SOLVE_COUNT = 0; + +double TOTAL_TIME = 0; +double ROOT_VALUE = 0; + +int SUBTOUR_CLUSTER_CLUSTER_COUNT = 0; +int SUBTOUR_NODE_CLUSTER_COUNT = 0; +int SUBTOUR_NODE_NODE_COUNT = 0; +int COMBS_COUNT = 0; + + static const struct option options_tab[] = { {"help", no_argument, 0, 'h'}, {"tsp", no_argument, 0, 't'}, {"gtsp", no_argument, 0, 'g'}, {"flow", no_argument, 0, 'f'}, diff --git a/src/main.h b/src/main.h index 5f64e38..9430cf0 100644 --- a/src/main.h +++ b/src/main.h @@ -7,4 +7,27 @@ extern int GEOMETRIC_DATA; extern int NODE_COUNT_RAND; extern int GRID_SIZE_RAND; +extern double *OPTIMAL_X; +extern double SUBTOUR_TIME; +extern double COMBS_TIME; + +extern double LP_SOLVE_TIME; +extern int LP_SOLVE_COUNT; +extern int LP_MAX_ROWS; +extern int LP_MAX_COLS; + +extern double CUT_POOL_TIME; +extern long CUT_POOL_MAX_MEMORY; + +extern int FLOW_MAX_FLOW_COUNT; + +extern double TOTAL_TIME; +extern double ROOT_VALUE; + +extern int SUBTOUR_CLUSTER_CLUSTER_COUNT; +extern int SUBTOUR_NODE_CLUSTER_COUNT; +extern int SUBTOUR_NODE_NODE_COUNT; + +extern int COMBS_COUNT; + #endif \ No newline at end of file