int main( void ){ Timer T(true); int final_nodes_num, edge_addition_num; final_nodes_num = 30000; edge_addition_num = 7; ListGraph mGr; lemon::Random mRandom; mRandom.seedFromTime(); vector<int> nodeChoice; set<int> mRndNodes; vector<int> targets(edge_addition_num, -1); int currentIndex = 0; // First targets are all nodes for(auto &v : targets){ v = currentIndex++; mGr.addNode(); } while (countNodes(mGr)<final_nodes_num ) { // Add new node and connect to targets currentIndex = mGr.id( mGr.addNode() ); for(const auto &v : targets ){ mGr.addEdge( mGr.nodeFromId( currentIndex ), mGr.nodeFromId( v ) ); } // Add the nodes, which were connented again nodeChoice.insert(nodeChoice.end(), targets.begin(), targets.end() ); nodeChoice.insert(nodeChoice.end(), edge_addition_num, currentIndex); mRndNodes.clear(); while (mRndNodes.size() < edge_addition_num) { mRndNodes.insert( nodeChoice[ mRandom.integer( nodeChoice.size() ) ] ); } targets.clear(); targets.insert(targets.begin(), mRndNodes.begin(), mRndNodes.end() ); } cout << "time: " << T.realTime() << endl; cout << countNodes( mGr) << endl; cout << countEdges( mGr) << endl; graphWriter( mGr, "/Users/sonneundasche/Documents/FLI/DATA/05 LEMON Graphs/BaraBasiTEST.txt") .run(); InDegMap<ListGraph> inDeg(mGr); graphWriter( mGr, "/Users/sonneundasche/Documents/FLI/DATA/05 LEMON Graphs/BaraBasi_Degree_TEST.txt") .nodeMap("degree", inDeg) .skipEdges() .run(); }
int main( void ){ Timer T(true); int init_nodes_num, final_nodes_num, edge_addition_num; init_nodes_num = 10; final_nodes_num = 50; edge_addition_num = 7; typedef ListEdgeSet< ListGraph > EdgeSet; ListGraph mListGraph; EdgeSet mNewEdges( mListGraph ); FullGraph fg(init_nodes_num); GraphCopy<FullGraph, ListGraph> cg( fg, mListGraph); // Create the seed nodes cg.run(); int mNumEdges = countEdges( mListGraph ); EdgeSet::Edge e; lemon::Random mRandom; mRandom.seedFromTime(); ListGraph::Node newNode, randNode; // new edges will be saved seperatly in an EdgeSet, not to change the original node degrees for ( int i = init_nodes_num; i < final_nodes_num; i++){ mNumEdges = countEdges( mListGraph ); mNewEdges.clear(); newNode = mListGraph.addNode(); while ( countEdges( mNewEdges ) != edge_addition_num ) { randNode = mListGraph.nodeFromId( mRandom[ mListGraph.maxNodeId() ] ) ; // --- CALCULATE THE PROBABILITY if ( mRandom.real() < (( (double)(countIncEdges(mListGraph, randNode)) / (double)( 2*mNumEdges ) )) ){ if ( findEdge( mNewEdges, newNode, randNode ) == INVALID){ // does the edge already exist? mNewEdges.addEdge( newNode, randNode ); } } } // Create the new edges in the original graph for (EdgeSet::EdgeIt e( mNewEdges ); e!=INVALID; ++e){ mListGraph.addEdge( mNewEdges.u( e ), mNewEdges.v(e) ); } } cout << T.realTime() << endl; cout << countEdges( mListGraph) << endl; cout << countEdges( fg ) << endl; }
// 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; }