/* init glp parameters. These should be changeable some way */ static void init_glp_parameters(void){ glp_init_smcp(&parm); parm.meth = GLP_DUAL; // PRIMAL,DUAL,DUALP parm.msg_lev = GLP_MSG_ERR; // ORR,ON,ALL,ERR parm.pricing = GLP_PT_PSE; // PSE,STD parm.r_test = GLP_RT_HAR; // HAR,STD parm.it_lim = 80000; // iteration limit parm.tm_lim = 10000; // time limit 10 seconds parm.out_frq = 80000; // output frequency parm.presolve = GLP_ON; // presolve, helps on numerical instability glp_term_out(GLP_OFF); // no terminal output }
int max_flow_lp(int nn, int ne, const int beg[/*1+ne*/], const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, int x[/*1+ne*/]) { glp_prob *lp; glp_smcp smcp; int i, k, nz, flow, *rn, *cn; double temp, *aa; /* create LP problem instance */ lp = glp_create_prob(); /* create LP rows; i-th row is the conservation condition of the * flow at i-th node, i = 1, ..., nn */ glp_add_rows(lp, nn); for (i = 1; i <= nn; i++) glp_set_row_bnds(lp, i, GLP_FX, 0.0, 0.0); /* create LP columns; k-th column is the elementary flow thru * k-th edge, k = 1, ..., ne; the last column with the number * ne+1 is the total flow through the network, which goes along * a dummy feedback edge from the sink to the source */ glp_add_cols(lp, ne+1); for (k = 1; k <= ne; k++) { xassert(cap[k] > 0); glp_set_col_bnds(lp, k, GLP_DB, -cap[k], +cap[k]); } glp_set_col_bnds(lp, ne+1, GLP_FR, 0.0, 0.0); /* build the constraint matrix; structurally this matrix is the * incidence matrix of the network, so each its column (including * the last column for the dummy edge) has exactly two non-zero * entries */ rn = xalloc(1+2*(ne+1), sizeof(int)); cn = xalloc(1+2*(ne+1), sizeof(int)); aa = xalloc(1+2*(ne+1), sizeof(double)); nz = 0; for (k = 1; k <= ne; k++) { /* x[k] > 0 means the elementary flow thru k-th edge goes from * node beg[k] to node end[k] */ nz++, rn[nz] = beg[k], cn[nz] = k, aa[nz] = -1.0; nz++, rn[nz] = end[k], cn[nz] = k, aa[nz] = +1.0; } /* total flow thru the network goes from the sink to the source * along the dummy feedback edge */ nz++, rn[nz] = t, cn[nz] = ne+1, aa[nz] = -1.0; nz++, rn[nz] = s, cn[nz] = ne+1, aa[nz] = +1.0; /* check the number of non-zero entries */ xassert(nz == 2*(ne+1)); /* load the constraint matrix into the LP problem object */ glp_load_matrix(lp, nz, rn, cn, aa); xfree(rn); xfree(cn); xfree(aa); /* objective function is the total flow through the network to * be maximized */ glp_set_obj_dir(lp, GLP_MAX); glp_set_obj_coef(lp, ne + 1, 1.0); /* solve LP instance with the (primal) simplex method */ glp_term_out(0); glp_adv_basis(lp, 0); glp_term_out(1); glp_init_smcp(&smcp); smcp.msg_lev = GLP_MSG_ON; smcp.out_dly = 5000; xassert(glp_simplex(lp, &smcp) == 0); xassert(glp_get_status(lp) == GLP_OPT); /* obtain optimal elementary flows thru edges of the network */ /* (note that the constraint matrix is unimodular and the data * are integral, so all elementary flows in basic solution should * also be integral) */ for (k = 1; k <= ne; k++) { temp = glp_get_col_prim(lp, k); x[k] = (int)floor(temp + .5); xassert(fabs(x[k] - temp) <= 1e-6); } /* obtain the maximum flow thru the original network which is the * flow thru the dummy feedback edge */ temp = glp_get_col_prim(lp, ne+1); flow = (int)floor(temp + .5); xassert(fabs(flow - temp) <= 1e-6); /* delete LP problem instance */ glp_delete_prob(lp); /* return to the calling program */ return flow; }
int main(int argc, char** argv) { int rank, num_p; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &num_p); MPI_Comm_rank(MPI_COMM_WORLD, &rank); int i; int n = 200; int N = 500; // Option processing extern char* optarg; const char* optstring = "n:N:"; int c; while ((c = getopt(argc, argv, optstring)) != -1) { switch (c) { case 'n': n = atoi(optarg); break; case 'N': N = atoi(optarg); break; } } glp_term_out(GLP_OFF); double* R; int* active_constr; if (rank == 0) { time_t curr_time; time(&curr_time); char* seed = ctime(&curr_time); R = malloc(N*num_p*(n-1)*sizeof(double)); generate_random_constraints(seed, N*num_p, n-1, R); active_constr = (int*) calloc(N*num_p, sizeof(int)); } double t0; if (rank == 0) { t0 = omp_get_wtime(); } double* R_local = malloc(N*(n-1)*sizeof(double)); int* active_constr_local = (int*) calloc(N, sizeof(int)); MPI_Scatter(R, N*(n-1), MPI_DOUBLE, R_local, N*(n-1), MPI_DOUBLE, 0, MPI_COMM_WORLD); int ridx[N]; for (i = 0; i < N; i++) { ridx[i] = i; } solve_lp(N, n, R_local, ridx, NULL, active_constr_local); MPI_Gather(active_constr_local, N, MPI_INT, active_constr, N, MPI_INT, 0, MPI_COMM_WORLD); // Re-solve with just the active constraints... double soln[n+1]; if (rank == 0) { int num_active_constr = 0; for (i = 0; i < N*num_p; i++) { num_active_constr += active_constr[i]; } int ridx[num_active_constr]; int count = 0; int i; for (i = 0; i < N*num_p; i++) { if (active_constr[i] == 1) { ridx[count] = i; count += 1; } } solve_lp(num_active_constr, n, R, ridx, soln, active_constr); // write_soln("soln.txt", n+1, soln); } if (rank == 0) { double t1 = omp_get_wtime(); printf("%d %g %g", num_p, t1-t0, soln[n]); for (i = 0; i < n; i++) { printf(" %g", soln[i]); } printf("\n"); } if (rank == 0) { free(R); free(active_constr); } free(R_local); free(active_constr_local); MPI_Finalize(); return 0; }
int c_simplex_sparse(int m, int n, DMAT(c), DMAT(b), DVEC(s)) { glp_prob *lp; lp = glp_create_prob(); glp_set_obj_dir(lp, GLP_MAX); int i,j,k; int tot = cr - n; glp_add_rows(lp, m); glp_add_cols(lp, n); //printf("%d %d\n",m,n); // the first n values for (k=1;k<=n;k++) { glp_set_obj_coef(lp, k, AT(c, k-1, 2)); //printf("%d %f\n",k,AT(c, k-1, 2)); } int * ia = malloc((1+tot)*sizeof(int)); int * ja = malloc((1+tot)*sizeof(int)); double * ar = malloc((1+tot)*sizeof(double)); for (k=1; k<= tot; k++) { ia[k] = rint(AT(c,k-1+n,0)); ja[k] = rint(AT(c,k-1+n,1)); ar[k] = AT(c,k-1+n,2); //printf("%d %d %f\n",ia[k],ja[k],ar[k]); } glp_load_matrix(lp, tot, ia, ja, ar); int t; for (i=1;i<=m;i++) { switch((int)rint(AT(b,i-1,0))) { case 0: { t = GLP_FR; break; } case 1: { t = GLP_LO; break; } case 2: { t = GLP_UP; break; } case 3: { t = GLP_DB; break; } default: { t = GLP_FX; break; } } glp_set_row_bnds(lp, i, t , AT(b,i-1,1), AT(b,i-1,2)); } for (j=1;j<=n;j++) { switch((int)rint(AT(b,m+j-1,0))) { case 0: { t = GLP_FR; break; } case 1: { t = GLP_LO; break; } case 2: { t = GLP_UP; break; } case 3: { t = GLP_DB; break; } default: { t = GLP_FX; break; } } glp_set_col_bnds(lp, j, t , AT(b,m+j-1,1), AT(b,m+j-1,2)); } glp_term_out(0); glp_simplex(lp, NULL); sp[0] = glp_get_status(lp); sp[1] = glp_get_obj_val(lp); for (k=1; k<=n; k++) { sp[k+1] = glp_get_col_prim(lp, k); } glp_delete_prob(lp); free(ia); free(ja); free(ar); return 0; }
int main(int argc, char ** argv){ if(argc < 2 || argc > 3){ std::cerr << "Usage: " << argv[0] << " GRAPH_FILENAME (CUT_FILENAME)" << std::endl; return 1; } // ---------- カットする辺の一覧 ChinesePostman::RouteNetwork cut; if(argc == 3){ ChinesePostman::EdgeWeightType cut_distance = ChinesePostman::read_from(argv[2], cut); if(cut_distance == 0){ std::cerr << "Error: When reading \"" << argv[2] << "\"" << std::endl; return 1; } } // ---------- グラフ ChinesePostman::RouteNetwork rn; ChinesePostman::EdgeWeightType total_distance = ChinesePostman::read_from(argv[1], rn); if(total_distance == 0){ std::cerr << "Error: When reading \"" << argv[1] << "\"" << std::endl; return 1; } // ---------- 「カットする辺の一覧」にある辺を除去するとともに、除去された辺に接する頂点を列挙する std::pair<ChinesePostman::Graph::edge_iterator, ChinesePostman::Graph::edge_iterator> edge_range = boost::edges(rn); std::vector<ChinesePostman::Graph::edge_descriptor> removed_edges_later_rn; // border_verticesの // キー:頂点 // 値のfirst:当該頂点が分割後のグラフのいくつめに属しているか(後ほど指定) // 値のsecond:当該頂点がmasked_vertices_origの何番目の要素であるか(後ほど指定) std::map< ChinesePostman::Graph::vertex_descriptor, std::pair<size_t, size_t> > border_vertices; // cutの辺集合に頂点が何度出現しているか std::map< ChinesePostman::Graph::vertex_descriptor, size_t > border_vertices_count, border_vertices_count_tmp; std::multiset<ChinesePostman::VirtualEdge> border_edges; std::pair<ChinesePostman::Graph::edge_iterator, ChinesePostman::Graph::edge_iterator> cutedge_range; for(ChinesePostman::Graph::edge_iterator ite = edge_range.first; ite != edge_range.second; ++ite){ cutedge_range = boost::edges(cut); ChinesePostman::Graph::edge_iterator cutite; for(cutite = cutedge_range.first; cutite != cutedge_range.second; ++cutite){ if(rn.edgeweight(*ite) == cut.edgeweight(*cutite) && equal_pair( rn.vertexname1_fromedge(*ite), rn.vertexname2_fromedge(*ite), cut.vertexname1_fromedge(*cutite), cut.vertexname2_fromedge(*cutite) )){ break; } } if(cutite != cutedge_range.second){ boost::remove_edge(*cutite, cut); removed_edges_later_rn.push_back(*ite); ChinesePostman::Graph::vertex_descriptor v1, v2; v1 = boost::source(*ite, rn); v2 = boost::target(*ite, rn); border_vertices.insert(std::make_pair(v1, std::make_pair(-1, -1))); border_vertices.insert(std::make_pair(v2, std::make_pair(-1, -1))); border_vertices_count_tmp[v1] += 1; border_vertices_count_tmp[v2] += 1; border_edges.insert(ChinesePostman::VirtualEdge(v1, v2, rn.edgeweight(*ite))); } } cutedge_range = boost::edges(cut); if(cutedge_range.first != cutedge_range.second){ std::cerr << "ERROR: Cutting edge not found - " << cut.vertexname1_fromedge(*(cutedge_range.first)) << ", " << cut.vertexname2_fromedge(*(cutedge_range.first)) << std::endl; return 1; } for(std::vector<ChinesePostman::Graph::edge_descriptor>::iterator ite = removed_edges_later_rn.begin(); ite != removed_edges_later_rn.end(); ++ite){ boost::remove_edge(*ite, rn); } // ---------- 連結要素に分割 ChinesePostman::RouteNetworkList division_result; ChinesePostman::VertexMapping vmap; // vmapは「元のグラフ上での頂点をキー、分割後のグラフ上での頂点を値とする連想配列」 rn.connectedcomponents(division_result, vmap); // ---------- 連結要素のそれぞれについて、2回通る頂点を決定する // ただしこのとき、境界の頂点は奇数回通るか偶数回通るかで場合わけする必要がある // すなわち、(2^[境界の頂点数])通りを試す必要がある // フラグが立っていれば「境界側から当該駅を利用する回数は偶数回」 // そうでなければ奇数回 std::vector< std::map< masked_vector<ChinesePostman::Graph::vertex_descriptor>::mask_type, std::deque<ChinesePostman::SubRoute> > > doubling_result(division_result.size()); std::vector< masked_vector<ChinesePostman::Graph::vertex_descriptor> > masked_vertices_orig(division_result.size()); std::vector< masked_vector<ChinesePostman::Graph::vertex_descriptor> > masked_vertices_sub(division_result.size()); size_t graph_component_id; graph_component_id = 0; for(ChinesePostman::RouteNetworkList::iterator itg = division_result.begin(); itg != division_result.end(); ++itg){ std::pair<ChinesePostman::Graph::vertex_iterator, ChinesePostman::Graph::vertex_iterator> vertex_range = boost::vertices(*itg); std::cerr << "Computing the graph of Stations[0] = \"" << (vertex_range.first == vertex_range.second ? std::string("<none>") : itg->vertexname(*vertex_range.first)) << "\", "; std::cerr << "Stations.size = " << boost::num_vertices(*itg) << ", "; std::cerr << "Edges.size = " << boost::num_edges(*itg) << std::endl; // border_vertices_subgraphは // 元のグラフ上での頂点をキー、分割後のグラフ(*itg)上での頂点を値とする // 連想配列で、分割境界上に位置しているもののみ集めたもの std::map<ChinesePostman::Graph::vertex_descriptor, ChinesePostman::Graph::vertex_descriptor> border_vertices_subgraph; for(ChinesePostman::Graph::vertex_iterator itv = vertex_range.first; itv != vertex_range.second; ++itv){ std::map< ChinesePostman::Graph::vertex_descriptor, std::pair<size_t, size_t> >::iterator itvb = std::find_if(border_vertices.begin(), border_vertices.end(), [&](const std::pair< ChinesePostman::Graph::vertex_descriptor, std::pair<size_t, size_t> > & v){ return vmap.at(v.first) == *itv; }); if(itvb != border_vertices.end()){ itvb->second.first = graph_component_id; border_vertices_subgraph[itvb->first] = *itv; border_vertices_count[*itv] = border_vertices_count_tmp[itvb->first]; } } // 番号付けしてmasked_vertices_*に格納する size_t count = 0; for(std::map<ChinesePostman::Graph::vertex_descriptor, ChinesePostman::Graph::vertex_descriptor>::iterator itv = border_vertices_subgraph.begin(); itv != border_vertices_subgraph.end(); ++itv){ border_vertices[itv->first].second = count; ++count; masked_vertices_orig[graph_component_id].push_back(itv->first); masked_vertices_sub[graph_component_id].push_back(itv->second); } // フロイド=ワーシャル ChinesePostman::DistanceMatrix distance_table; boost::floyd_warshall_all_pairs_shortest_paths(*itg, distance_table); // すべてのborder_vertices_subgraph「の部分集合」について // 2回通るべき辺を決定する #ifdef CHINESE_POSTMAN_DEBUG_PROGRESS glp_term_out(GLP_ON); #else glp_term_out(GLP_OFF); #endif // CHINESE_POSTMAN_DEBUG_PROGRESS do{ #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << " Border nodes visited for even-number times (mask: " << masked_vertices_sub[graph_component_id].mask() << ", size: " << masked_vertices_sub[graph_component_id].size() << ")"; std::cerr << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP masked_vertices_orig[graph_component_id].next(); masked_vertices_sub[graph_component_id].next(); #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << " Border nodes visited for even-number times (mask: " << masked_vertices_sub[graph_component_id].mask() << ", size: " << masked_vertices_sub[graph_component_id].size() << ")"; for(size_t i = 0; i < masked_vertices_sub[graph_component_id].size(); ++i){ if(masked_vertices_sub[graph_component_id].has(i)){ std::cerr << " " << itg->vertexname(masked_vertices_sub[graph_component_id][i]); } } std::cerr << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP // 組み合わせを求める if(itg->find_doubled_edges(distance_table, doubling_result[graph_component_id][masked_vertices_sub[graph_component_id].mask()], masked_vertices_sub[graph_component_id], border_vertices_count)){ #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << "[[Computed!!]]" << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP }else{ #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << "[[Skipped!]]" << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP doubling_result[graph_component_id].erase(masked_vertices_sub[graph_component_id].mask()); } }while(!(masked_vertices_sub[graph_component_id].emptymask())); ++graph_component_id; } // カット用の辺を1回通る/2回通るというすべての組み合わせについて // 各部分の距離と組み合わせていく masked_vector<ChinesePostman::VirtualEdge> border_edge_subsets(border_edges); std::vector< masked_vector<ChinesePostman::Graph::vertex_descriptor>::mask_type > mask_compo(division_result.size()); ChinesePostman::EdgeWeightType best_distance = 0; std::vector<const std::deque<ChinesePostman::SubRoute> *> temp_doubling_result(division_result.size()), best_doubling_result(division_result.size()); masked_vector<ChinesePostman::VirtualEdge>::mask_type best_border_edge_subset_mask; boost::multiprecision::cpp_int percentage = 0, new_percentage; boost::multiprecision::cpp_int max_mask = 1; max_mask = (max_mask << border_edge_subsets.size()) - 1; if(max_mask == 0) max_mask = 1; do{ new_percentage = border_edge_subsets.mask() * 100 / max_mask; if(new_percentage == 100 || new_percentage >= percentage + 10){ percentage = new_percentage; std::cerr << "Border edge doubling: " << percentage << "%" << std::endl; } border_edge_subsets.next(); // カット用の辺を1回通る/2回通るという組み合わせ(border_edge_subsets)について // 対応する境界上の頂点を偶数回通るか奇数回通るか決定する std::fill(mask_compo.begin(), mask_compo.end(), 0); std::pair<size_t, size_t> flag4vertex; ChinesePostman::EdgeWeightType cut_distance = 0; ChinesePostman::EdgeWeightType compo_distance = 0; #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << "----------"; std::cerr << "Doubling the following cut edges:"; #endif // CHINESE_POSTMAN_DEBUG_DUMP for(size_t i = 0; i < border_edge_subsets.size(); ++i){ if(border_edge_subsets.has(i)){ #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << " " << rn.vertexname(border_edge_subsets[i].v1); std::cerr << "-" << rn.vertexname(border_edge_subsets[i].v2); #endif // CHINESE_POSTMAN_DEBUG_DUMP cut_distance += border_edge_subsets[i].weight; flag4vertex = border_vertices[border_edge_subsets[i].v1]; boost::multiprecision::bit_flip(mask_compo[flag4vertex.first], flag4vertex.second); flag4vertex = border_vertices[border_edge_subsets[i].v2]; boost::multiprecision::bit_flip(mask_compo[flag4vertex.first], flag4vertex.second); } } #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP // 境界上の頂点を偶数回通るか奇数回通るかの組み合わせが // 実際に実現可能か確認する ChinesePostman::RouteNetworkList::iterator itg; graph_component_id = 0; for(itg = division_result.begin(); itg != division_result.end(); ++itg){ if(doubling_result[graph_component_id].find(mask_compo[graph_component_id]) == doubling_result[graph_component_id].end()) break; ++graph_component_id; } if(itg != division_result.end()){ #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << "Not possible" << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP continue; } // (実際に可能なら)距離を合算したものを取得する #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << "Doubled edges optimization: " << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP graph_component_id = 0; for(itg = division_result.begin(); itg != division_result.end(); ++itg){ temp_doubling_result[graph_component_id] = &(doubling_result[graph_component_id][mask_compo[graph_component_id]]); for(std::deque<ChinesePostman::SubRoute>::const_iterator its = temp_doubling_result[graph_component_id]->cbegin(); its != temp_doubling_result[graph_component_id]->cend(); ++its){ #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << " " << its->v1; std::cerr << "-" << its->v2; #endif // CHINESE_POSTMAN_DEBUG_DUMP } compo_distance += sum_of_distance(*(temp_doubling_result[graph_component_id])); ++graph_component_id; } #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cerr << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP #ifdef CHINESE_POSTMAN_DEBUG_DUMP std::cout << "Doubled edge weight in cuts: " << cut_distance << std::endl; std::cout << "Doubled edge weight in optimization: " << compo_distance << std::endl; #endif // CHINESE_POSTMAN_DEBUG_DUMP if(best_distance == 0 || best_distance > cut_distance + compo_distance){ best_distance = cut_distance + compo_distance; best_doubling_result.swap(temp_doubling_result); best_border_edge_subset_mask = border_edge_subsets.mask(); } }while(!(border_edge_subsets.emptymask())); std::cout << "# ---------- Best Result ----------" << std::endl; std::cout << "# Total distance of all graph edges = " << total_distance << std::endl; std::cout << "# Total distance of doubled edges = " << best_distance << std::endl; std::cout << "# Total distance of traversed edges = " << total_distance + best_distance << std::endl; std::cout << "# Edges traversed twice in cuts" << std::endl; border_edge_subsets.set_mask(best_border_edge_subset_mask); for(size_t i = 0; i < border_edge_subsets.size(); ++i){ if(border_edge_subsets.has(i)){ std::cout << border_edge_subsets[i].weight << " "; std::cout << rn.vertexname(border_edge_subsets[i].v1) << " "; std::cout << rn.vertexname(border_edge_subsets[i].v2) << std::endl; } } for(graph_component_id = 0; graph_component_id < division_result.size(); ++graph_component_id){ std::cout << "# Edges traversed twice in component " << (graph_component_id+1) << std::endl; for(std::deque<ChinesePostman::SubRoute>::const_iterator its = best_doubling_result[graph_component_id]->cbegin(); its != best_doubling_result[graph_component_id]->cend(); ++its){ std::cout << its->weight << " "; std::cout << its->v1 << " "; std::cout << its->v2 << std::endl; } } return 0; }
int main2(int argc, char *argv[]){ char * file_model; char * file_data; if (argc < 5){ usage(); exit(1); } file_model = file_data = NULL; GRB_out = GLPK_out = verbose = 1; for(int i=1 ; i<=argc-1 ; i++){ if (strcmp(argv[i],"-m")==0) file_model = argv[i+1]; if (strcmp(argv[i],"-d")==0) file_data = argv[i+1]; if (strcmp(argv[i],"-v")==0) verbose = 1; if (strcmp(argv[i],"--glpk_out")==0) GLPK_out = 1; if (strcmp(argv[i],"--grb_out")==0) GRB_out = 1; if (strcmp(argv[i],"--glpk_mip_gap")==0) glpk_iparm_mip_gap = atof(argv[i+1]); if (strcmp(argv[i],"--glpk_tol_int")==0) glpk_iparm_tol_int = atof(argv[i+1]); if (strcmp(argv[i],"--glpk_tol_obj")==0) glpk_iparm_tol_obj = atof(argv[i+1]); } if ((file_model==NULL) || (file_data == NULL)){ usage(); fprintf(stderr, "Error no model or data files provided\n"); freeMem(); } /** GLPK: Open environment **/ mip = glp_create_prob(); tran = glp_mpl_alloc_wksp(); glp_term_out(GLPK_out?GLP_ON:GLP_OFF); /** GLPK: Read model written in MathProg **/ ret = glp_mpl_read_model(tran, file_model, 1); if (ret){ fprintf(stderr, "Error on translating model\n"); freeMem(); } /** GLPK: Read data for MathProg **/ ret = glp_mpl_read_data(tran, file_data); if (ret){ fprintf(stderr, "Error on translating data\n"); freeMem(); } /** GLPK: Generate model (merge data an model) **/ ret = glp_mpl_generate(tran, NULL); if (ret){ fprintf(stderr, "Error on generating model\n"); freeMem(); } /** GLPK: Generate Build Model **/ glp_mpl_build_prob(tran, mip); wrapper_params wpar; wpar.grb_out = GRB_out; wpar.glp_out = GLPK_out; solve_glp_grb(mip,&wpar); /** GLPK: Perform postprocessing **/ ret = glp_mpl_postsolve(tran, mip, GLP_MIP); if (ret != 0) fprintf(stderr, "Error on postsolving model\n"); /** GLPK: free structures **/ if (tran) glp_mpl_free_wksp(tran); if (mip) glp_delete_prob(mip); if (retGRB) printf("ERROR: %s\n", GRBgeterrormsg(env)); /** GUROBI: free structures **/ if (model) GRBfreemodel(model); if (env) GRBfreeenv(env); printf("Done.\nGLPK -> GUROBI -> GLPK wrapper v0.1 (2010)\n"); exit(0); }
bool isFeasible() { int nCons; int coef1[MAXNEDGES], coef2[MAXNEDGES]; int ind[MAXNEDGES+1]; double val[MAXNEDGES+1]; glp_prob * lp = glp_create_prob(); glp_set_obj_dir(lp, GLP_MAX); glp_add_cols(lp, nEdges+1); for (int i=0; i<nEdges+1; i++) glp_set_col_bnds(lp, i+1, GLP_LO, 0, 0); glp_set_obj_coef(lp, nEdges+1, 1); nCons = 0; for (int i=0; i<nEdges; i++) { nCons++; glp_add_rows(lp,1); glp_set_row_bnds(lp, nCons, GLP_UP, 0, 0); ind[1] = nEdges+1; val[1] = 1; //gamma <= l_e ind[2] = i+1; val[2] = -1; glp_set_mat_row(lp, nCons, 2, ind, val); } for (int m=0; m<k; m++) { int first = -1; for (int i=0; i<paths[m].n; i++) if (paths[m].isShort[i]) { first = i; break; } assert(first>=0); setCoef(coef1, m, first); for (int i=first+1; i<paths[m].n; i++) if (paths[m].isShort[i]) { setCoef(coef2, m, i); nCons++; glp_add_rows(lp,1); glp_set_row_bnds(lp, nCons, GLP_FX, 0, 0); int nEle = 0; for (int j=0; j<nEdges; j++) if (coef1[j] ^ coef2[j]) { nEle++; ind[nEle] = j+1; val[nEle] = (coef1[j])? 1:-1; } glp_set_mat_row(lp, nCons, nEle, ind, val); } for (int i=0; i<paths[m].n; i++) if (!paths[m].isShort[i]){ setCoef(coef2, m, i); nCons++; glp_add_rows(lp,1); glp_set_row_bnds(lp, nCons, GLP_UP, 0, 0); int nEle = 0; for (int j=0; j<nEdges; j++) if (coef1[j] ^ coef2[j]) { nEle++; ind[nEle] = j+1; val[nEle] = (coef1[j])? 1:-1; } glp_set_mat_row(lp, nCons, nEle, ind, val); } } nCons++; glp_add_rows(lp,1); glp_set_row_bnds(lp, nCons, GLP_UP, 0, 1); for (int j=0; j<nEdges; j++) { ind[j+1] = j+1; val[j+1] = 1; } glp_set_mat_row(lp, nCons, nEdges, ind, val); glp_term_out(GLP_OFF); glp_simplex(lp, NULL); double ret = glp_get_obj_val(lp); glp_delete_prob(lp); return (ret>0); }
// read in all necessary elements for retrieving the LP/MILP void Rglpk_read_file (char **file, int *type, int *lp_direction_of_optimization, int *lp_n_constraints, int *lp_n_objective_vars, int *lp_n_values_in_constraint_matrix, int *lp_n_integer_vars, int *lp_n_binary_vars, char **lp_prob_name, char **lp_obj_name, int *lp_verbosity) { int status; extern glp_prob *lp; glp_tran *tran; const char *str; // Turn on/off Terminal Output if (*lp_verbosity==1) glp_term_out(GLP_ON); else glp_term_out(GLP_OFF); // create problem object if (lp) glp_delete_prob(lp); lp = glp_create_prob(); // read file -> gets stored as an GLPK problem object 'lp' // which file type do we have? switch (*type){ case 1: // Fixed (ancient) MPS Format, param argument currently NULL status = glp_read_mps(lp, GLP_MPS_DECK, NULL, *file); break; case 2: // Free (modern) MPS format, param argument currently NULL status = glp_read_mps(lp, GLP_MPS_FILE, NULL, *file); break; case 3: // CPLEX LP Format status = glp_read_lp(lp, NULL, *file); break; case 4: // MATHPROG Format (based on lpx_read_model function) tran = glp_mpl_alloc_wksp(); status = glp_mpl_read_model(tran, *file, 0); if (!status) { status = glp_mpl_generate(tran, NULL); if (!status) { glp_mpl_build_prob(tran, lp); } } glp_mpl_free_wksp(tran); break; } // if file read successfully glp_read_* returns zero if ( status != 0 ) { glp_delete_prob(lp); lp = NULL; error("Reading file %s failed", *file); } // retrieve problem name str = glp_get_prob_name(lp); if (str){ *lp_prob_name = (char *) str; } // retrieve name of objective function str = glp_get_obj_name(lp); if (str){ *lp_obj_name = (char *) str; } // retrieve optimization direction flag *lp_direction_of_optimization = glp_get_obj_dir(lp); // retrieve number of constraints *lp_n_constraints = glp_get_num_rows(lp); // retrieve number of objective variables *lp_n_objective_vars = glp_get_num_cols(lp); // retrieve number of non-zero elements in constraint matrix *lp_n_values_in_constraint_matrix = glp_get_num_nz(lp); // retrieve number of integer variables *lp_n_integer_vars = glp_get_num_int(lp); // retrieve number of binary variables *lp_n_binary_vars = glp_get_num_bin(lp); }
// retrieve all missing values of LP/MILP void Rglpk_retrieve_MP_from_file (char **file, int *type, int *lp_n_constraints, int *lp_n_objective_vars, double *lp_objective_coefficients, int *lp_constraint_matrix_i, int *lp_constraint_matrix_j, double *lp_constraint_matrix_values, int *lp_direction_of_constraints, double *lp_right_hand_side, double *lp_left_hand_side, int *lp_objective_var_is_integer, int *lp_objective_var_is_binary, int *lp_bounds_type, double *lp_bounds_lower, double *lp_bounds_upper, int *lp_ignore_first_row, int *lp_verbosity, char **lp_constraint_names, char **lp_objective_vars_names ) { extern glp_prob *lp; glp_tran *tran; const char *str; int i, j, lp_column_kind, tmp; int ind_offset, status; // Turn on/off Terminal Output if (*lp_verbosity==1) glp_term_out(GLP_ON); else glp_term_out(GLP_OFF); // create problem object if (lp) glp_delete_prob(lp); lp = glp_create_prob(); // read file -> gets stored as an GLPK problem object 'lp' // which file type do we have? switch (*type){ case 1: // Fixed (ancient) MPS Format, param argument currently NULL status = glp_read_mps(lp, GLP_MPS_DECK, NULL, *file); break; case 2: // Free (modern) MPS format, param argument currently NULL status = glp_read_mps(lp, GLP_MPS_FILE, NULL, *file); break; case 3: // CPLEX LP Format status = glp_read_lp(lp, NULL, *file); break; case 4: // MATHPROG Format (based on lpx_read_model function) tran = glp_mpl_alloc_wksp(); status = glp_mpl_read_model(tran, *file, 0); if (!status) { status = glp_mpl_generate(tran, NULL); if (!status) { glp_mpl_build_prob(tran, lp); } } glp_mpl_free_wksp(tran); break; } // if file read successfully glp_read_* returns zero if ( status != 0 ) { glp_delete_prob(lp); lp = NULL; error("Reading file %c failed.", *file); } if(*lp_verbosity==1) Rprintf("Retrieve column specific data ...\n"); if(glp_get_num_cols(lp) != *lp_n_objective_vars) { glp_delete_prob(lp); lp = NULL; error("The number of columns is not as specified"); } // retrieve column specific data (values, bounds and type) for (i = 0; i < *lp_n_objective_vars; i++) { lp_objective_coefficients[i] = glp_get_obj_coef(lp, i+1); // Note that str must not be freed befor we have returned // from the .C call in R! str = glp_get_col_name(lp, i+1); if (str){ lp_objective_vars_names[i] = (char *) str; } lp_bounds_type[i] = glp_get_col_type(lp, i+1); lp_bounds_lower[i] = glp_get_col_lb (lp, i+1); lp_bounds_upper[i] = glp_get_col_ub (lp, i+1); lp_column_kind = glp_get_col_kind(lp, i+1); // set to TRUE if objective variable is integer or binary switch (lp_column_kind){ case GLP_IV: lp_objective_var_is_integer[i] = 1; break; case GLP_BV: lp_objective_var_is_binary[i] = 1; break; } } ind_offset = 0; if(*lp_verbosity==1) Rprintf("Retrieve row specific data ...\n"); if(glp_get_num_rows(lp) != *lp_n_constraints) { glp_delete_prob(lp); lp = NULL; error("The number of rows is not as specified"); } // retrieve row specific data (right hand side, direction of constraints) for (i = *lp_ignore_first_row; i < *lp_n_constraints; i++) { lp_direction_of_constraints[i] = glp_get_row_type(lp, i+1); str = glp_get_row_name(lp, i + 1); if (str) { lp_constraint_names[i] = (char *) str; } // the right hand side. Note we don't allow for double bounded or // free auxiliary variables if( lp_direction_of_constraints[i] == GLP_LO ) lp_right_hand_side[i] = glp_get_row_lb(lp, i+1); if( lp_direction_of_constraints[i] == GLP_UP ) lp_right_hand_side[i] = glp_get_row_ub(lp, i+1); if( lp_direction_of_constraints[i] == GLP_FX ) lp_right_hand_side[i] = glp_get_row_lb(lp, i+1); if( lp_direction_of_constraints[i] == GLP_DB ){ lp_right_hand_side[i] = glp_get_row_ub(lp, i+1); lp_left_hand_side[i] = glp_get_row_lb(lp, i+1); } tmp = glp_get_mat_row(lp, i+1, &lp_constraint_matrix_j[ind_offset-1], &lp_constraint_matrix_values[ind_offset-1]); if (tmp > 0) for (j = 0; j < tmp; j++) lp_constraint_matrix_i[ind_offset+j] = i+1; ind_offset += tmp; } if(*lp_verbosity==1) Rprintf("Done.\n"); }