int main(int argc, char *argv[]) { int nt; Digraph g; // graph declaration string digraph_steiner_filename; DiNodeName vname(g); // name of graph nodes Digraph::NodeMap<double> px(g),py(g); // xy-coodinates for each node Digraph::NodeMap<int> vcolor(g);// color of nodes Digraph::ArcMap<int> ecolor(g); // color of edges ArcWeight lpvar(g); // used to obtain the contents of the LP variables ArcWeight weight(g); // edge weights Digraph::ArcMap<GRBVar> x(g); // binary variables for each arc vector <DiNode> V; int seed=0; srand48(1); // uncomment one of these lines to change default pdf reader, or insert new one //set_pdfreader("open"); // pdf reader for Mac OS X //set_pdfreader("xpdf"); // pdf reader for Linux //set_pdfreader("evince"); // pdf reader for Linux // double cutoff; // used to prune non promissing branches (of the B&B tree) if (argc!=2) {cout<< endl << "Usage: "<< argv[0]<<" <digraph_steiner_filename>"<< endl << endl; cout << "Examples: " << argv[0] << " gr_berlin52.steiner" << endl; cout << " " << argv[0] << " gr_usa48.steiner" << endl << endl; exit(0);} digraph_steiner_filename = argv[1]; //int time_limit = 3600; // solution must be obtained within time_limit seconds GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); model.getEnv().set(GRB_IntParam_LazyConstraints, 1); model.getEnv().set(GRB_IntParam_Seed, seed); model.set(GRB_StringAttr_ModelName, "Oriented Steiner Tree with GUROBI"); // prob. name model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // is a minimization problem ReadListDigraphSteiner(digraph_steiner_filename,g,vname,weight,px,py,1,nt,V); Steiner_Instance T(g,vname,px,py,weight,nt,V); //for (DiNodeIt v(g);v!=INVALID;++v){ if(v==T.V[0])vcolor[v]=RED; else vcolor[v]=BLUE;} //for (int i=1;i<T.nt;i++) vcolor[T.V[i]] = MAGENTA; //for (ArcIt e(g); e != INVALID; ++e) ecolor[e] = BLUE; //ViewListDigraph(g,vname,px,py,vcolor,ecolor,"Triangulated graph"); // Generate the binary variables and the objective function // Add one binary variable for each edge and set its cost in the objective function for (Digraph::ArcIt e(g); e != INVALID; ++e) { char name[100]; sprintf(name,"X_%s_%s",vname[g.source(e)].c_str(),vname[g.target(e)].c_str()); x[e] = model.addVar(0.0, 1.0, weight[e],GRB_BINARY,name); } model.update(); // run update to use model inserted variables try { //if (time_limit >= 0) model.getEnv().set(GRB_DoubleParam_TimeLimit,time_limit); //model.getEnv().set(GRB_DoubleParam_ImproveStartTime,10); //try better sol. aft. 10s // if (cutoff > 0) model.getEnv().set(GRB_DoubleParam_Cutoff, cutoff ); ConnectivityCuts cb = ConnectivityCuts(T , x); model.setCallback(&cb); model.update(); //model.write("model.lp"); system("cat model.lp"); model.optimize(); double soma=0.0; for (DiNodeIt v(g);v!=INVALID;++v) vcolor[v]=BLUE; // all nodes BLUE for (int i=0;i<T.nt;i++) vcolor[T.V[i]]=MAGENTA; // change terminals to MAGENTA vcolor[T.V[0]]=RED; // change root to RED for (Digraph::ArcIt e(g); e!=INVALID; ++e) { lpvar[e] = x[e].get(GRB_DoubleAttr_X); if (lpvar[e] > 1.0 - EPS) { soma += weight[e]; ecolor[e] = RED; } else ecolor[e] = NOCOLOR; } cout << "Steiner Tree Value = " << soma << endl; ViewListDigraph(g,vname,px,py,vcolor,ecolor, "Steiner Tree cost in graph with "+IntToString(T.nnodes)+ " nodes and "+IntToString(T.nt)+" terminals: "+DoubleToString(soma)); } catch (...) {cout << "Error during callback..." << endl; } return 0; }
// ATENÇÃO: Não modifique a assinatura deste método. bool brach_and_bound999999(TSP_Data_R &tsp, const vector<DNode> &terminais, const vector<DNode> &postos, const DNode source, int delta, int maxTime, vector<DNode> &sol, double &lbound){ // Converte o TSP direcionado para um nao direcionado com duas arestas ListGraph graph; EdgeValueMap weights(graph); // Adiciona os nos for (ListDigraph::NodeIt u(tsp.g); u!=INVALID; ++u) { Node v = graph.addNode(); } // Adiciona as arestas for (ListDigraph::ArcIt ait(tsp.g); ait!=INVALID; ++ait) { // pega os dois nos incidentes Arc a(ait); DNode u = tsp.g.source(a); DNode v = tsp.g.target(a); // cria a mesma aresta no grafo não direcionado Node gu = graph.nodeFromId(tsp.g.id(u)); Node gv = graph.nodeFromId(tsp.g.id(v)); // insere a aresta no grafo nao direcionado Edge e = graph.addEdge(gu, gv); // Atribui pesos as arestas weights[e] = tsp.weight[a]; } NodeStringMap nodename(graph); NodePosMap posicaox(graph); NodePosMap posicaoy(graph); TSP_Data utsp(graph, nodename, posicaox, posicaoy, weights); // utiliza o convertido ListGraph::EdgeMap<GRBVar> x(graph); GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); // TODO: [Opcional] Comente a linha abaixo caso não queira inserir cortes durante a execução do B&B model.getEnv().set(GRB_IntParam_LazyConstraints, 1); model.getEnv().set(GRB_IntParam_Seed, 0); model.set(GRB_StringAttr_ModelName, "TSPR - TSP with Refueling"); // name to the problem model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // is a minimization problem // Add one binary variable for each arc and also sets its cost in the objective function for (EdgeIt e(utsp.g); e!=INVALID; ++e) { char name[100]; Edge edge(e); unsigned uid = utsp.g.id(utsp.g.u(edge)); unsigned vid = utsp.g.id(utsp.g.v(edge)); sprintf(name,"x_%s_%s",tsp.vname[tsp.g.nodeFromId(uid)].c_str(),tsp.vname[tsp.g.nodeFromId(vid)].c_str()); x[e] = model.addVar(0.0, 1.0, utsp.weight[e],GRB_BINARY,name); } model.update(); // run update to use model inserted variables // converte os terminais e os postos vector<Node> uterminais; for (auto t : terminais) { unsigned tid = tsp.g.id(t); uterminais.push_back(utsp.g.nodeFromId(tid)); } NodeBoolMap upostos(utsp.g, false); for (auto p: postos) { unsigned pid = tsp.g.id(p); // upostos.push_back(utsp.g.nodeFromId(pid)); upostos[utsp.g.nodeFromId(pid)] = true; } // Adicione restrições abaixo // (1) Nós terminais devem ser visitados exatamente uma vez for (auto v : uterminais) { GRBLinExpr expr = 0; for (IncEdgeIt e(utsp.g,v); e!=INVALID; ++e){ expr += x[e]; } model.addConstr(expr == 2 ); } // (3) Nó source sempre presente no início do caminho Node usource = utsp.g.nodeFromId(tsp.g.id(source)); GRBLinExpr expr = 0; for (IncEdgeIt e(utsp.g,usource); e!=INVALID; ++e){ expr += x[e]; } model.addConstr(expr >= 1 ); try { model.update(); // Process any pending model modifications. //if (maxTime >= 0) model.getEnv().set(GRB_DoubleParam_TimeLimit,maxTime); subtourelim cb = subtourelim(utsp , x, usource, upostos, delta); model.setCallback(&cb); // TODO: [Opcional] Pode-se utilizar o valor de uma solução heurística p/ acelerar o algoritmo B&B (cutoff value). //cutoff = tsp.BestCircuitValue-MY_EPS; double cutoff = 0.0; if (cutoff > MY_EPS) model.getEnv().set(GRB_DoubleParam_Cutoff, cutoff ); model.update(); // Process any pending model modifications. model.optimize(); // Obtém o status da otimização int status = model.get(GRB_IntAttr_Status); if(status == GRB_INFEASIBLE || status == GRB_INF_OR_UNBD){ cout << "Modelo inviavel ou unbounded." << endl; return false; } // Limitante inferior e superior do modelo //lbound = model.get(GRB_DoubleAttr_ObjBoundC); if( model.get(GRB_IntAttr_SolCount) <= 0 ){ cout << "Modelo nao encontrou nenhuma solucao viavel no tempo. LowerBound = " << lbound << endl; return false; } else if (status == GRB_OPTIMAL){ if(verbose) cout << "O modelo foi resolvido ate a otimalidade." << endl; } else { if(verbose) cout << "O modelo encontrou uma solucao sub-otima (i.e. nao ha garantia de otimalidade)." << endl; } double custo_solucao = model.get(GRB_DoubleAttr_ObjVal); int uncovered=0; EdgeBoolMap cover(utsp.g, false); for (EdgeIt e(utsp.g); e!=INVALID; ++e) { if (BinaryIsOne(x[e].get(GRB_DoubleAttr_X))) { cover[e] = true; uncovered++; } } sol.push_back(tsp.g.nodeFromId(utsp.g.id(usource))); convertSol(x, sol, tsp, utsp, usource, cover, uncovered); // Calculo manual do custo da solução (deve ser igual ao ObjVal do Gurobi). double soma=0.0; ArcName aname(tsp.g); vector<Arc> edgesSol; ArcColorMap acolor(tsp.g); // if( verbose ) cout << "####### " << endl << "Edges of Solution (B&B):" << endl; // for (EdgeIt e(utsp.g); e!=INVALID; ++e){ // if (BinaryIsOne(x[e].get(GRB_DoubleAttr_X))){ // Note que se este método serve para variáveis binárias, p/ inteiras terá de usar outro método. // soma += utsp.weight[e]; // edgesSol.push_back(tsp.g.arcFromId(utsp.g.id(e))); // if( verbose) cout << "(" << tsp.vname[tsp.g.nodeFromId(utsp.g.id(utsp.g.u(e)))] << "," << tsp.vname[tsp.g.nodeFromId(utsp.g.id(utsp.g.v(e)))] << ")" << endl; // acolor[tsp.g.arcFromId(utsp.g.id(e))] = BLUE; // } // } // if( verbose ) cout << "####### " << endl; if( verbose ) cout << "####### " << endl << "Edges of Solution (B&B):" << endl; DNode u = sol[0]; for (int i=1; i<sol.size(); i++) { DNode v = sol[i]; soma += tsp.AdjMatD.Cost(u,v); if ( verbose ) cout << "(" << tsp.vname[u] << "," << tsp.vname[v] << ")" << endl; u = v; } if( verbose ) cout << "####### " << endl; if( verbose ) cout << "Custo calculado pelo B&B = "<< soma << " / " << custo_solucao << endl; if( verbose ){ cout << "Caminho encontrado a partir do vértice de origem (" << tsp.vname[source] << "): "; for(auto node : sol){ cout << tsp.vname[node] << " "; } // Obs: O caminho é gerado a partir do nó source, se o conjunto de arestas retornado pelo B&B for desconexo, o caminho retornado por 'path_search' será incompleto. cout << endl << "Custo calculado da solucao (caminho a partir do no origem) = " << solutionCost(tsp, sol) << endl; ostringstream out; out << "TSP with Refueling B&B, cost= " << custo_solucao; ViewListDigraph(tsp.g, tsp.vname, tsp.posx, tsp.posy, tsp.vcolor, acolor, out.str()); } return true; } catch(GRBException e) { cerr << "Gurobi exception has been thrown." << endl; cerr << "Error code = " << e.getErrorCode() << endl; cerr << e.getMessage(); } catch (...) { cout << "Model is infeasible" << endl; return false; } return false; }
int main(int argc, char *argv[]) { if (argc < 2) { cout << "Usage: tsp_c++ filename" << endl; return 1; } int n = atoi(argv[1]); double* x = new double[n]; double* y = new double[n]; for (int i = 0; i < n; i++) { x[i] = ((double) rand())/RAND_MAX; y[i] = ((double) rand())/RAND_MAX; } GRBEnv *env = NULL; GRBVar **vars = new GRBVar*[n]; try { int i, j; env = new GRBEnv(); GRBModel model = GRBModel(*env); // Must disable dual reductions when using lazy constraints model.getEnv().set(GRB_IntParam_DualReductions, 0); // Create binary decision variables for (i = 0; i < n; i++) vars[i] = model.addVars(n); model.update(); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { vars[i][j].set(GRB_CharAttr_VType, GRB_BINARY); vars[i][j].set(GRB_DoubleAttr_Obj, distance(x, y, i, j)); vars[i][j].set(GRB_StringAttr_VarName, "x_"+itos(i)+"_"+itos(j)); } } // Integrate new variables model.update(); // Degree-2 constraints for (i = 0; i < n; i++) { GRBLinExpr expr = 0; for (j = 0; j < n; j++) expr += vars[i][j]; model.addConstr(expr == 2, "deg2_"+itos(i)); } // Forbid edge from node back to itself for (i = 0; i < n; i++) vars[i][i].set(GRB_DoubleAttr_UB, 0); // Symmetric TSP for (i = 0; i < n; i++) for (j = 0; j < i; j++) model.addConstr(vars[i][j] == vars[j][i]); // Set callback function subtourelim cb = subtourelim(vars, n); model.setCallback(&cb); // Optimize model model.optimize(); // Extract solution if (model.get(GRB_IntAttr_SolCount) > 0) { double **sol = new double*[n]; for (i = 0; i < n; i++) sol[i] = model.get(GRB_DoubleAttr_X, vars[i], n); int* tour = new int[n]; int len; findsubtour(n, sol, &len, tour); cout << "Tour: "; for (i = 0; i < len; i++) cout << tour[i] << " "; cout << endl; for (i = 0; i < n; i++) delete[] sol[i]; delete[] sol; delete[] tour; } } catch (GRBException e) { cout << "Error number: " << e.getErrorCode() << endl; cout << e.getMessage() << endl; } catch (...) { cout << "Error during optimization" << endl; } for (int i = 0; i < n; i++) delete[] vars[i]; delete[] vars; delete[] x; delete[] y; delete env; return 0; }
int main(int argc, char *argv[]) { int time_limit; char name[1000]; double cutoff=0.0; ListGraph g; EdgeWeight lpvar(g); EdgeWeight weight(g); NodeName vname(g); ListGraph::NodeMap<double> posx(g),posy(g); string filename; int seed=1; // uncomment one of these lines to change default pdf reader, or insert new one //set_pdfreader("open"); // pdf reader for Mac OS X //set_pdfreader("xpdf"); // pdf reader for Linux //set_pdfreader("evince"); // pdf reader for Linux srand48(seed); time_limit = 3600; // solution must be obtained within time_limit seconds if (argc!=2) {cout<< endl << "Usage: "<< argv[0]<<" <graph_filename>"<<endl << endl << "Example: " << argv[0] << " gr_berlin52" << endl << " " << argv[0] << " gr_att48" << endl << endl; exit(0);} else if (!FileExists(argv[1])) {cout<<"File "<<argv[1]<<" does not exist."<<endl; exit(0);} filename = argv[1]; // Read the graph if (!ReadListGraph(filename,g,vname,weight,posx,posy)) {cout<<"Error reading graph file "<<argv[1]<<"."<<endl;exit(0);} TSP_Data tsp(g,vname,posx,posy,weight); ListGraph::EdgeMap<GRBVar> x(g); GRBEnv env = GRBEnv(); GRBModel model = GRBModel(env); #if GUROBI_NEWVERSION model.getEnv().set(GRB_IntParam_LazyConstraints, 1); model.getEnv().set(GRB_IntParam_Seed, seed); #else model.getEnv().set(GRB_IntParam_DualReductions, 0); // Dual reductions must be disabled when using lazy constraints #endif model.set(GRB_StringAttr_ModelName, "Undirected TSP with GUROBI"); // name to the problem model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE); // is a minimization problem // Add one binary variable for each edge and also sets its cost in the objective function for (ListGraph::EdgeIt e(g); e!=INVALID; ++e) { sprintf(name,"x_%s_%s",vname[g.u(e)].c_str(),vname[g.v(e)].c_str()); x[e] = model.addVar(0.0, 1.0, weight[e],GRB_BINARY,name); } model.update(); // run update to use model inserted variables // Add degree constraint for each node (sum of solution edges incident to a node is 2) for (ListGraph::NodeIt v(g); v!=INVALID; ++v) { GRBLinExpr expr; for (ListGraph::IncEdgeIt e(g,v); e!=INVALID; ++e) expr += x[e]; //aqui model.addConstr(expr == 2 ); what? ignorou! model.addConstr(expr == 2 ); } try { model.update(); // Process any pending model modifications. if (time_limit >= 0) model.getEnv().set(GRB_DoubleParam_TimeLimit,time_limit); subtourelim cb = subtourelim(tsp , x); model.setCallback(&cb); tsp.max_perturb2opt_it = 200; //1000; // number of iterations used in heuristic TSP_Perturb2OPT TSP_Perturb2OPT(tsp); if (tsp.BestCircuitValue < DBL_MAX) cutoff = tsp.BestCircuitValue-BC_EPS; // // optimum value for gr_a280=2579, gr_xqf131=566.422, gr_drilling198=15808.652 if (cutoff > 0) model.getEnv().set(GRB_DoubleParam_Cutoff, cutoff ); model.update(); // Process any pending model modifications. model.optimize(); double soma=0.0; for (ListGraph::EdgeIt e(g); e!=INVALID; ++e) { lpvar[e] = x[e].get(GRB_DoubleAttr_X); if (lpvar[e] > 1-BC_EPS ) { soma += weight[e]; if ( (vname[g.u(e)] == "243")||(vname[g.v(e)] == "243") || (vname[g.u(e)] == "242")||(vname[g.v(e)] == "242") ) { cout << "Achei, x("<< vname[g.u(e)] << " , " << vname[g.v(e)] << " = " << lpvar[e] <<"\n"; } } } cout << "Solution cost = "<< soma << endl; Update_Circuit(tsp,x); // Update the circuit in x to tsp circuit variable (if better) ViewTspCircuit(tsp); }catch (...) { if (tsp.BestCircuitValue < DBL_MAX) { cout << "Heuristic obtained optimum solution" << endl; ViewTspCircuit(tsp); return 0; }else { cout << "Graph is infeasible" << endl; return 1; } } }
int main (int argc, char * argv[]) { chrono :: steady_clock :: time_point tBegin = chrono :: steady_clock :: now(); string I ("0"); ulint timeLimit = 10; if (argc >= 2) { I = string (argv[1]); } if (argc >= 3) { timeLimit = atoi(argv[2]); } ulint nComplete, k, t, n, m, root; double d; cin >> nComplete >> d >> k >> t >> n >> m >> root; vector <ulint> penalty (nComplete); // vector with de penalties of each vectex vector < list < pair <ulint, ulint> > > adj (nComplete); // adjacency lists for the graph for (ulint v = 0; v < nComplete; v++) { cin >> penalty[v]; } vector <ulint> solutionV (nComplete, 0); // reading solution vertices for (ulint i = 0; i < n; i++) { ulint v; cin >> v; solutionV[v] = 1; } vector < pair < pair <ulint, ulint> , ulint> > E (m); // vector of edges with the format ((u, v), w) map < pair <ulint, ulint>, ulint> mE; // map an edge to its ID vector < vector <ulint> > paths (m); // reading graph for (ulint e = 0; e < m; e++) { ulint u, v, w, pathSize; cin >> u >> v >> w >> pathSize; adj[u].push_back(make_pair(v, w)); adj[v].push_back(make_pair(u, w)); E[e] = make_pair(make_pair(u, v), w); mE[make_pair(u, v)] = e; mE[make_pair(v, u)] = e; paths[e] = vector <ulint> (pathSize); for (ulint i = 0; i < pathSize; i++) { cin >> paths[e][i]; } } try { string N = itos(nComplete); stringstream ssD; ssD << fixed << setprecision(1) << d; string D = ssD.str(); D.erase(remove(D.begin(), D.end(), '.'), D.end()); string K = itos(k); string T = itos(t); ifstream remainingTimeFile ("./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/remainingTime.txt"); lint remainingTime = 0; if (remainingTimeFile.is_open()) { remainingTimeFile >> remainingTime; } if (remainingTime > 0) { timeLimit += remainingTime; } GRBEnv env = GRBEnv(); env.set(GRB_IntParam_LazyConstraints, 1); env.set(GRB_IntParam_LogToConsole, 0); env.set(GRB_StringParam_LogFile, "./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/log2.txt"); env.set(GRB_DoubleParam_TimeLimit, ((double) timeLimit)); GRBModel model = GRBModel(env); model.getEnv().set(GRB_IntParam_LazyConstraints, 1); model.getEnv().set(GRB_IntParam_LogToConsole, 0); model.getEnv().set(GRB_StringParam_LogFile, "./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/log2.txt"); model.getEnv().set(GRB_DoubleParam_TimeLimit, ((double) timeLimit)); vector <GRBVar> y (nComplete); // ∀ v ∈ V for (ulint v = 0; v < nComplete; v++) { // y_v ∈ {0.0, 1.0} y[v] = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "y_" + itos(v)); } vector <GRBVar> x (m); // ∀ e ∈ E for (ulint e = 0; e < m; e++) { ulint u, v; u = E[e].first.first; v = E[e].first.second; // y_e ∈ {0.0, 1.0} x[e] = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "x_" + itos(u) + "_" + itos(v)); } model.update(); GRBLinExpr obj = 0.0; // obj = ∑ ce * xe for (ulint e = 0; e < m; e++) { ulint w; w = E[e].second; obj += w * x[e]; } // obj += ∑ πv * (1 - yv) for (ulint v = 0; v < nComplete; v++) { obj += penalty[v] * (1.0 - y[v]); } model.setObjective(obj, GRB_MINIMIZE); // yu == 1 model.addConstr(y[root] == 1.0, "c_0"); // dominance // ∀ v ∈ V for (ulint v = 0; v < nComplete; v++) { if (solutionV[v] == 1) { GRBLinExpr constr = 0.0; constr += y[v]; model.addConstr(constr == 1, "c_1_" + itos(v)); } } // each vertex must have exactly two edges adjacent to itself // ∀ v ∈ V for (ulint v = 0; v < nComplete; v++) { // ∑ xe == 2 * yv , e ∈ δ({v}) GRBLinExpr constr = 0.0; for (list < pair <ulint, ulint> > :: iterator it = adj[v].begin(); it != adj[v].end(); it++) { ulint w = (*it).first; // destination ulint e = mE[make_pair(v, w)]; constr += x[e]; } model.addConstr(constr == 2.0 * y[v], "c_2_" + itos(v)); } subtourelim cb = subtourelim(y, x, nComplete, m, E, mE, root); model.setCallback(&cb); model.optimize(); if (model.get(GRB_IntAttr_SolCount) > 0) { ulint solutionCost = 0; set <ulint> solutionVectices; vector < pair <ulint, ulint> > solutionEdges; solutionCost = round(model.get(GRB_DoubleAttr_ObjVal)); for (ulint v = 0; v < nComplete; v++) { if (y[v].get(GRB_DoubleAttr_X) >= 0.5) { solutionVectices.insert(v); } } for (ulint e = 0; e < m; e++) { if (x[e].get(GRB_DoubleAttr_X) >= 0.5) { for (ulint i = 0; i < paths[e].size() - 1; i++) { pair <ulint, ulint> edge; if (paths[e][i] < paths[e][i + 1]) { edge.first = paths[e][i]; edge.second = paths[e][i + 1]; } else { edge.first = paths[e][i + 1]; edge.second = paths[e][i]; } solutionEdges.push_back(edge); } } } cout << solutionVectices.size() << ' ' << solutionEdges.size() << ' ' << solutionCost << endl; for (set <ulint> :: iterator it = solutionVectices.begin(); it != solutionVectices.end(); it++) { ulint v = *it; cout << v << endl; } for (vector < pair <ulint, ulint> > :: iterator it = solutionEdges.begin(); it != solutionEdges.end(); it++) { pair <ulint, ulint> e = *it; cout << e.first << " " << e.second << endl; } } else { cout << "0 0 0" << endl; } // exporting model model.write("./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/model2.lp"); ofstream objValFile ("./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/objVal2.txt", ofstream :: out); objValFile << model.get(GRB_DoubleAttr_ObjVal); objValFile.close(); ofstream gapFile ("./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/gap2.txt", ofstream :: out); gapFile << model.get(GRB_DoubleAttr_MIPGap); gapFile.close(); chrono :: steady_clock :: time_point tEnd = chrono :: steady_clock :: now(); chrono :: nanoseconds elapsedTime = chrono :: duration_cast <chrono :: nanoseconds> (tEnd - tBegin); ofstream elapsedTimeFile ("./output/N" + N + "D" + D + "K" + K + "T" + T + "I" + I + "/elapsedTime2.txt", ofstream :: out); elapsedTimeFile << elapsedTime.count(); elapsedTimeFile.close(); } catch (GRBException e) {