//============================================================== // Copyright Intel Corporation // // SPDX-License-Identifier: MIT // ============================================================= #include #include #include #include #include #include // dpc_common.hpp can be found in the dev-utilities include folder. // e.g., $ONEAPI_ROOT/dev-utilities//include/dpc_common.hpp #include "dpc_common.hpp" #include "glpsol.h" // This code sample demonstrates how to split the host and FPGA kernel code into // separate compilation units so that they can be separately recompiled. // Consult the README for a detailed discussion. // - host.cpp (this file) contains exclusively code that executes on the host. // - kernel.cpp contains almost exclusively code that executes on the device. // - kernel.hpp contains only the forward declaration of a function containing // the device code. #include "kernel.hpp" using namespace sycl; // Create an exception handler for asynchronous SYCL exceptions static auto exception_handler = [](sycl::exception_list e_list) { for (std::exception_ptr const &e : e_list) { try { std::rethrow_exception(e); } catch (std::exception const &e) { #if _DEBUG std::cout << "Failure" << std::endl; #endif std::terminate(); } } }; template void printMatrix(std::vector &vec, int col, std::string msg) { std::cout << msg << ":" << std::endl << "[" << std::endl; for (size_t i=0; i 1) { std::cout << ",\t"; } if (i%col == col-1) { std::cout << std::endl; } } std::cout << "]" << std::endl; } template void printVec(std::vector &vec, std::string msg) { std::cout << msg << ": "; std::cout << "["; for (size_t i=0; i 1) { std::cout << ", "; } } std::cout << "]" << std::endl; } int main2() { std::vector a = { 2, 1, 1, 1, 0, 0, 1, 3, 2, 0, 1, 0, 2, 1, 2, 0, 0, 1}; std::vector c = {-6, -5, -4, 0, 0, 0}; std::vector b = {180, 300, 240}; std::vector resultFlags = {-1, -1, -1}; // Select either the FPGA emulator or FPGA device #if defined(FPGA_EMULATOR) ext::intel::fpga_emulator_selector device_selector; #else ext::intel::fpga_selector device_selector; #endif try { // Create a queue bound to the chosen device. // If the device is unavailable, a SYCL runtime exception is thrown. queue q(device_selector, exception_handler); device d = q.get_device(); // Print out the device information used for the kernel code. std::cout << "Running on device: " << d.get_info() << "\n"; // make sure the device supports USM device allocations if (!d.get_info()) { std::cerr << "ERROR: The selected device does not support USM device" << " allocations\n"; return 1; } printMatrix(a, 6, "a"); printVec(resultFlags, "result flags"); // The definition of this function is in a different compilation unit, // so host and device code can be separately compiled. double timePassed = RunKernel(q, a, b, c, resultFlags); std::cout << "------------------------" << std::endl; printMatrix(a, 6, "a"); printVec(resultFlags, "result flags"); std::cout << std::endl << std::endl; std::cout << "timePassed: " << timePassed << std::endl; } catch (exception const &e) { // Catches exceptions in the host code std::cerr << "Caught a SYCL host exception:\n" << e.what() << "\n"; // Most likely the runtime couldn't find FPGA hardware! if (e.code().value() == CL_DEVICE_NOT_FOUND) { std::cerr << "If you are targeting an FPGA, please ensure that your " "system has a correctly configured FPGA board.\n"; std::cerr << "Run sys_check in the oneAPI root directory to verify.\n"; std::cerr << "If you are targeting the FPGA emulator, compile with " "-DFPGA_EMULATOR.\n"; } std::terminate(); } std::cout << "done\n"; return 0; } int runOnFPGA() { // Select either the FPGA emulator or FPGA device #if defined(FPGA_EMULATOR) ext::intel::fpga_emulator_selector device_selector; #else ext::intel::fpga_selector device_selector; #endif try { // Create a queue bound to the chosen device. // If the device is unavailable, a SYCL runtime exception is thrown. queue q(device_selector, exception_handler); device d = q.get_device(); // Print out the device information used for the kernel code. std::cout << "Running on device: " << d.get_info() << "\n"; // make sure the device supports USM device allocations if (!d.get_info()) { std::cerr << "ERROR: The selected device does not support USM device" << " allocations\n"; return 1; } int *parallel = malloc_shared(1000, q); double timePassed = 0; //RunKernel(q, a, b, c, resultFlags); std::cout << std::endl; std::cout << "timePassed: " << timePassed << std::endl; } catch (exception const &e) { // Catches exceptions in the host code std::cerr << "Caught a SYCL host exception:\n" << e.what() << "\n"; // Most likely the runtime couldn't find FPGA hardware! if (e.code().value() == CL_DEVICE_NOT_FOUND) { std::cerr << "If you are targeting an FPGA, please ensure that your " "system has a correctly configured FPGA board.\n"; std::cerr << "Run sys_check in the oneAPI root directory to verify.\n"; std::cerr << "If you are targeting the FPGA emulator, compile with " "-DFPGA_EMULATOR.\n"; } std::terminate(); } std::cout << "done\n"; return 0; } void hellothere(void *tmpCSA) { int *a = static_cast(tmpCSA); std::cout << "callback from simplex..." << std::endl; std::cout << "test output a:" << *a << " " << std::endl; *a = 9999; } int main(int argc, char *argv[]) { /* stand-alone LP/MIP solver */ struct csa _csa, *csa = &_csa; int ret; #if 0 /* 10/VI-2013 */ glp_long start; #else double start; #endif /* perform initialization */ csa->prob = glp_create_prob(); glp_get_bfcp(csa->prob, &csa->bfcp); glp_init_smcp(&csa->smcp); csa->smcp.presolve = GLP_ON; glp_init_iptcp(&csa->iptcp); glp_init_iocp(&csa->iocp); csa->iocp.presolve = GLP_ON; csa->tran = NULL; csa->graph = NULL; csa->format = FMT_MPS_FILE; csa->in_file = NULL; csa->ndf = 0; csa->out_dpy = NULL; csa->seed = 1; csa->solution = SOL_BASIC; csa->in_res = NULL; csa->dir = 0; csa->scale = 1; csa->out_sol = NULL; csa->out_res = NULL; csa->out_ranges = NULL; csa->check = 0; csa->new_name = NULL; #if 1 /* 18/I-2018 */ csa->hide = 0; #endif csa->out_mps = NULL; csa->out_freemps = NULL; csa->out_cpxlp = NULL; csa->out_glp = NULL; #if 0 csa->out_pb = NULL; csa->out_npb = NULL; #endif #if 1 /* 06/VIII-2011 */ csa->out_cnf = NULL; #endif csa->log_file = NULL; csa->crash = USE_ADV_BASIS; csa->ini_file = NULL; csa->exact = 0; csa->xcheck = 0; csa->nomip = 0; #if 1 /* 15/VIII-2011 */ csa->minisat = 0; csa->use_bnd = 0; csa->obj_bnd = 0; #endif #if 1 /* 11/VII-2013 */ csa->use_sol = NULL; #endif /* parse command-line parameters */ ret = parse_cmdline(csa, argc, argv); if (ret < 0) { ret = EXIT_SUCCESS; goto done; } if (ret > 0) { ret = EXIT_FAILURE; goto done; } /*--------------------------------------------------------------*/ /* remove all output files specified in the command line */ if (csa->out_dpy != NULL) remove(csa->out_dpy); if (csa->out_sol != NULL) remove(csa->out_sol); if (csa->out_res != NULL) remove(csa->out_res); if (csa->out_ranges != NULL) remove(csa->out_ranges); if (csa->out_mps != NULL) remove(csa->out_mps); if (csa->out_freemps != NULL) remove(csa->out_freemps); if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp); if (csa->out_glp != NULL) remove(csa->out_glp); #if 0 if (csa->out_pb != NULL) remove(csa->out_pb); if (csa->out_npb != NULL) remove(csa->out_npb); #endif #if 1 /* 06/VIII-2011 */ if (csa->out_cnf != NULL) remove(csa->out_cnf); #endif if (csa->log_file != NULL) remove(csa->log_file); /*--------------------------------------------------------------*/ /* open log file, if required */ if (csa->log_file != NULL) { if (glp_open_tee(csa->log_file)) { xprintf("Unable to create log file\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* print version information */ print_version(1); /*--------------------------------------------------------------*/ /* print parameters specified in the command line */ if (argc > 1) { int k, len = INT_MAX; xprintf("Parameter(s) specified in the command line:"); for (k = 1; k < argc; k++) { if (len > 72) xprintf("\n"), len = 0; xprintf(" %s", argv[k]); len += 1 + strlen(argv[k]); } xprintf("\n"); } /*--------------------------------------------------------------*/ /* read problem data from the input file */ if (csa->in_file == NULL) { xprintf("No input problem file specified; try %s --help\n", argv[0]); ret = EXIT_FAILURE; goto done; } if (csa->format == FMT_MPS_DECK) { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL, csa->in_file); if (ret != 0) err1: { xprintf("MPS file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_MPS_FILE) { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL, csa->in_file); if (ret != 0) goto err1; } else if (csa->format == FMT_LP) { ret = glp_read_lp(csa->prob, NULL, csa->in_file); if (ret != 0) { xprintf("CPLEX LP file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_GLP) { ret = glp_read_prob(csa->prob, 0, csa->in_file); if (ret != 0) { xprintf("GLPK LP/MIP file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_MATHPROG) { int k; /* allocate the translator workspace */ csa->tran = glp_mpl_alloc_wksp(); /* set seed value */ if (csa->seed == 0x80000000) #if 0 /* 10/VI-2013 */ { csa->seed = glp_time().lo; #else { csa->seed = (int)fmod(glp_time(), 1000000000.0); #endif xprintf("Seed value %d will be used\n", csa->seed); } glp_mpl_init_rand(csa->tran, csa->seed); /* read model section and optional data section */ if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0)) err2: { xprintf("MathProg model processing error\n"); ret = EXIT_FAILURE; goto done; } /* read optional data section(s), if necessary */ for (k = 1; k <= csa->ndf; k++) { if (glp_mpl_read_data(csa->tran, csa->in_data[k])) goto err2; } /* generate the model */ if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2; /* build the problem instance from the model */ glp_mpl_build_prob(csa->tran, csa->prob); } else if (csa->format == FMT_MIN_COST) { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_mincost_lp(csa->prob, csa->graph, GLP_ON, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost)); glp_set_prob_name(csa->prob, csa->in_file); } else if (csa->format == FMT_MAX_FLOW) { int s, t; csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_maxflow(csa->graph, &s, &t, offsetof(a_data, cap), csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t, offsetof(a_data, cap)); glp_set_prob_name(csa->prob, csa->in_file); } #if 1 /* 06/VIII-2011 */ else if (csa->format == FMT_CNF) { ret = glp_read_cnfsat(csa->prob, csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_set_prob_name(csa->prob, csa->in_file); } #endif else xassert(csa != csa); /*--------------------------------------------------------------*/ /* change problem name, if required */ if (csa->new_name != NULL) glp_set_prob_name(csa->prob, csa->new_name); /* change optimization direction, if required */ if (csa->dir != 0) glp_set_obj_dir(csa->prob, csa->dir); /* sort elements of the constraint matrix */ glp_sort_matrix(csa->prob); #if 1 /* 18/I-2018 */ /*--------------------------------------------------------------*/ /* remove all symbolic names from problem object, if required */ if (csa->hide) { int i, j; glp_set_obj_name(csa->prob, NULL); glp_delete_index(csa->prob); for (i = glp_get_num_rows(csa->prob); i >= 1; i--) glp_set_row_name(csa->prob, i, NULL); for (j = glp_get_num_cols(csa->prob); j >= 1; j--) glp_set_col_name(csa->prob, j, NULL); } #endif /*--------------------------------------------------------------*/ /* write problem data in fixed MPS format, if required */ if (csa->out_mps != NULL) { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL, csa->out_mps); if (ret != 0) { xprintf("Unable to write problem in fixed MPS format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in free MPS format, if required */ if (csa->out_freemps != NULL) { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL, csa->out_freemps); if (ret != 0) { xprintf("Unable to write problem in free MPS format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in CPLEX LP format, if required */ if (csa->out_cpxlp != NULL) { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp); if (ret != 0) { xprintf("Unable to write problem in CPLEX LP format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in GLPK format, if required */ if (csa->out_glp != NULL) { ret = glp_write_prob(csa->prob, 0, csa->out_glp); if (ret != 0) { xprintf("Unable to write problem in GLPK format\n"); ret = EXIT_FAILURE; goto done; } } #if 0 /* write problem data in OPB format, if required */ if (csa->out_pb != NULL) { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0); if (ret != 0) { xprintf("Unable to write problem in OPB format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in normalized OPB format, if required */ if (csa->out_npb != NULL) { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1); if (ret != 0) { xprintf( "Unable to write problem in normalized OPB format\n"); ret = EXIT_FAILURE; goto done; } } #endif #if 1 /* 06/VIII-2011 */ /* write problem data in DIMACS CNF-SAT format, if required */ if (csa->out_cnf != NULL) { ret = glp_write_cnfsat(csa->prob, csa->out_cnf); if (ret != 0) { xprintf( "Unable to write problem in DIMACS CNF-SAT format\n"); ret = EXIT_FAILURE; goto done; } } #endif /*--------------------------------------------------------------*/ /* if only problem data check is required, skip computations */ if (csa->check) { #if 1 /* 29/III-2016 */ /* report problem characteristics */ int j, cnt = 0; xprintf("--- Problem Characteristics ---\n"); xprintf("Number of rows = %8d\n", glp_get_num_rows(csa->prob)); xprintf("Number of columns = %8d\n", glp_get_num_cols(csa->prob)); xprintf("Number of non-zeros (matrix) = %8d\n", glp_get_num_nz(csa->prob)); for (j = glp_get_num_cols(csa->prob); j >= 1; j--) { if (glp_get_obj_coef(csa->prob, j) != 0.0) cnt++; } xprintf("Number of non-zeros (objrow) = %8d\n", cnt); #endif ret = EXIT_SUCCESS; goto done; } /*--------------------------------------------------------------*/ /* determine the solution type */ if (!csa->nomip && glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0) { if (csa->solution == SOL_INTERIOR) { xprintf("Interior-point method is not able to solve MIP pro" "blem; use --simplex\n"); ret = EXIT_FAILURE; goto done; } csa->solution = SOL_INTEGER; } /*--------------------------------------------------------------*/ /* if solution is provided, read it and skip computations */ if (csa->in_res != NULL) { if (csa->solution == SOL_BASIC) ret = glp_read_sol(csa->prob, csa->in_res); else if (csa->solution == SOL_INTERIOR) ret = glp_read_ipt(csa->prob, csa->in_res); else if (csa->solution == SOL_INTEGER) ret = glp_read_mip(csa->prob, csa->in_res); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to read problem solution\n"); ret = EXIT_FAILURE; goto done; } goto skip; } #if 1 /* 11/VII-2013 */ /*--------------------------------------------------------------*/ /* if initial MIP solution is provided, read it */ if (csa->solution == SOL_INTEGER && csa->use_sol != NULL) { ret = glp_read_mip(csa->prob, csa->use_sol); if (ret != 0) { xprintf("Unable to read initial MIP solution\n"); ret = EXIT_FAILURE; goto done; } csa->iocp.use_sol = GLP_ON; } #endif /*--------------------------------------------------------------*/ /* scale the problem data, if required */ if (csa->scale) { if (csa->solution == SOL_BASIC && !csa->smcp.presolve || csa->solution == SOL_INTERIOR || csa->solution == SOL_INTEGER && !csa->iocp.presolve) glp_scale_prob(csa->prob, GLP_SF_AUTO); } /*--------------------------------------------------------------*/ /* construct starting LP basis */ if (csa->solution == SOL_BASIC && !csa->smcp.presolve || csa->solution == SOL_INTEGER && !csa->iocp.presolve) { if (csa->crash == USE_STD_BASIS) glp_std_basis(csa->prob); else if (csa->crash == USE_ADV_BASIS) glp_adv_basis(csa->prob, 0); else if (csa->crash == USE_CPX_BASIS) glp_cpx_basis(csa->prob); else if (csa->crash == USE_INI_BASIS) { ret = glp_read_sol(csa->prob, csa->ini_file); if (ret != 0) { xprintf("Unable to read initial basis\n"); ret = EXIT_FAILURE; goto done; } } else xassert(csa != csa); } /*--------------------------------------------------------------*/ /* solve the problem */ start = glp_time(); if (csa->solution == SOL_BASIC) { if (!csa->exact) { glp_set_bfcp(csa->prob, &csa->bfcp); glp_simplex2(csa->prob, &csa->smcp, hellothere); if (csa->xcheck) { if (csa->smcp.presolve && glp_get_status(csa->prob) != GLP_OPT) xprintf("If you need to check final basis for non-opt" "imal solution, use --nopresol\n"); else glp_exact(csa->prob, &csa->smcp); } if (csa->out_sol != NULL || csa->out_res != NULL) { if (csa->smcp.presolve && glp_get_status(csa->prob) != GLP_OPT) xprintf("If you need actual output for non-optimal solut" "ion, use --nopresol\n"); } } else glp_exact(csa->prob, &csa->smcp); } else if (csa->solution == SOL_INTERIOR) glp_interior(csa->prob, &csa->iptcp); #if 1 /* 15/VIII-2011 */ else if (csa->solution == SOL_INTEGER && csa->minisat) { if (glp_check_cnfsat(csa->prob) == 0) glp_minisat1(csa->prob); else glp_intfeas1(csa->prob, csa->use_bnd, csa->obj_bnd); } #endif else if (csa->solution == SOL_INTEGER) { glp_set_bfcp(csa->prob, &csa->bfcp); if (!csa->iocp.presolve) glp_simplex2(csa->prob, &csa->smcp, hellothere); #if 0 csa->iocp.msg_lev = GLP_MSG_DBG; csa->iocp.pp_tech = GLP_PP_NONE; #endif #ifdef GLP_CB_FUNC /* 05/IV-2016 */ { extern void GLP_CB_FUNC(glp_tree *, void *); csa->iocp.cb_func = GLP_CB_FUNC; csa->iocp.cb_info = NULL; } #endif glp_intopt(csa->prob, &csa->iocp); } else xassert(csa != csa); /*--------------------------------------------------------------*/ /* display statistics */ xprintf("Time used: %.1f secs\n", glp_difftime(glp_time(), start)); #if 0 /* 16/II-2012 */ { glp_long tpeak; char buf[50]; glp_mem_usage(NULL, NULL, NULL, &tpeak); xprintf("Memory used: %.1f Mb (%s bytes)\n", xltod(tpeak) / 1048576.0, xltoa(tpeak, buf)); } #else { size_t tpeak; glp_mem_usage(NULL, NULL, NULL, &tpeak); xprintf("Memory used: %.1f Mb (%.0f bytes)\n", (double)tpeak / 1048576.0, (double)tpeak); } #endif /*--------------------------------------------------------------*/ skip: /* postsolve the model, if necessary */ if (csa->tran != NULL) { if (csa->solution == SOL_BASIC) { if (!(glp_get_status(csa->prob) == GLP_OPT || glp_get_status(csa->prob) == GLP_FEAS)) ret = -1; else ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL); } else if (csa->solution == SOL_INTERIOR) { if (!(glp_ipt_status(csa->prob) == GLP_OPT || glp_ipt_status(csa->prob) == GLP_FEAS)) ret = -1; else ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT); } else if (csa->solution == SOL_INTEGER) { if (!(glp_mip_status(csa->prob) == GLP_OPT || glp_mip_status(csa->prob) == GLP_FEAS)) ret = -1; else ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP); } else xassert(csa != csa); if (ret > 0) { xprintf("Model postsolving error\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* write problem solution in printable format, if required */ if (csa->out_sol != NULL) { if (csa->solution == SOL_BASIC) ret = glp_print_sol(csa->prob, csa->out_sol); else if (csa->solution == SOL_INTERIOR) ret = glp_print_ipt(csa->prob, csa->out_sol); else if (csa->solution == SOL_INTEGER) ret = glp_print_mip(csa->prob, csa->out_sol); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to write problem solution\n"); ret = EXIT_FAILURE; goto done; } } /* write problem solution in printable format, if required */ if (csa->out_res != NULL) { if (csa->solution == SOL_BASIC) ret = glp_write_sol(csa->prob, csa->out_res); else if (csa->solution == SOL_INTERIOR) ret = glp_write_ipt(csa->prob, csa->out_res); else if (csa->solution == SOL_INTEGER) ret = glp_write_mip(csa->prob, csa->out_res); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to write problem solution\n"); ret = EXIT_FAILURE; goto done; } } /* write sensitivity analysis report, if required */ if (csa->out_ranges != NULL) { if (csa->solution == SOL_BASIC) { if (glp_get_status(csa->prob) == GLP_OPT) { if (glp_bf_exists(csa->prob)) ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0, csa->out_ranges); if (ret != 0) { xprintf("Unable to write sensitivity analysis repo" "rt\n"); ret = EXIT_FAILURE; goto done; } } else { ret = glp_factorize(csa->prob); if (ret == 0) goto ranges; xprintf("Cannot produce sensitivity analysis report d" "ue to error in basis factorization (glp_factorize" " returned %d); try --nopresol\n", ret); } } else xprintf("Cannot produce sensitivity analysis report for " "non-optimal basic solution\n"); } else xprintf("Cannot produce sensitivity analysis report for int" "erior-point or MIP solution\n"); } /*--------------------------------------------------------------*/ /* all seems to be ok */ ret = EXIT_SUCCESS; /*--------------------------------------------------------------*/ done: /* delete the LP/MIP problem object */ if (csa->prob != NULL) glp_delete_prob(csa->prob); /* free the translator workspace, if necessary */ if (csa->tran != NULL) glp_mpl_free_wksp(csa->tran); /* delete the network problem object, if necessary */ if (csa->graph != NULL) glp_delete_graph(csa->graph); #if 0 /* 23/XI-2015 */ xassert(gmp_pool_count() == 0); gmp_free_mem(); #endif /* close log file, if necessary */ if (csa->log_file != NULL) glp_close_tee(); /* check that no memory blocks are still allocated */ #if 0 /* 16/II-2012 */ { int count; glp_long total; glp_mem_usage(&count, NULL, &total, NULL); if (count != 0) xerror("Error: %d memory block(s) were lost\n", count); xassert(count == 0); xassert(total.lo == 0 && total.hi == 0); } #else { int count; size_t total; glp_mem_usage(&count, NULL, &total, NULL); if (count != 0) xerror("Error: %d memory block(s) were lost\n", count); xassert(total == 0); } #endif /* free the GLPK environment */ glp_free_env(); /* return to the control program */ return ret; }