Ejemplo n.º 1
0
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();
    
  }
void ViewTspCircuit(TSP_Data &tsp)
{
  ListGraph h;
  ListGraph::NodeMap<string> h_vname(h);  // node names
  ListGraph::NodeMap<Node> h_g2h(tsp.g);  // maps a node of g to a node of h
  ListGraph::NodeMap<double> h_posx(h);
  ListGraph::NodeMap<double> h_posy(h);
  ListGraph::NodeMap<int> vcolor(h);   // color of the vertices
  ListGraph::EdgeMap<int> acolor(h);  // color of edges
  ListGraph::EdgeMap<string> aname(h);  // name of edges
  for (ListGraph::NodeIt v(tsp.g); v!=INVALID; ++v) {
    Node hv;
    hv = h.addNode();
    h_g2h[v] = hv;
    h_posx[hv] = tsp.posx[v];
    h_posy[hv] = tsp.posy[v];
    h_vname[hv] = tsp.vname[v];
    vcolor[hv] = BLUE;
  }
  for (int i=0;i<tsp.NNodes;i++) {
    ListGraph::Node u,v;
    ListGraph::Edge a;
    u = tsp.BestCircuit[i]; 
    v = tsp.BestCircuit[(i+1) % tsp.NNodes]; 
    a = h.addEdge(h_g2h[u] , h_g2h[v]);
    aname[a] = "";
    acolor[a] = BLUE;
  }
  ViewListGraph(h,h_vname,aname,h_posx,h_posy,vcolor,acolor,"TSP Circuit with cost "+DoubleToString(tsp.BestCircuitValue));
}
Ejemplo n.º 3
0
//Generate a random complete euclidean ListGraph
bool GenerateRandomEuclideanListGraph(ListGraph &g,
		  NodeStringMap &vname, // node names
		  NodePosMap& px, // x-position of the nodes
		  NodePosMap& py, // y-position of the nodes
		  EdgeValueMap& weight, // weight of edges
		  int n, // number of nodes
		  double SizeX, // coordinate x is a random number in [0,SizeX)
		  double SizeY) // coordinate y is a random number in [0,SizeY)
{
  int i,j; // n=number of nodes
  Node *V;
  V = new Node[n];
  if (V==NULL){
    cout << "Memory allocation error, number of nodes " << n << " too large\n";
    exit(0);}
  
  for (i=0;i<n;i++) {   // insert nodes (random points in [0,100] x [0,100] )
    V[i] = g.addNode(); // generate a new node
    px[V[i]] = SizeX*drand48();
    py[V[i]] = SizeY*drand48();
    vname[V[i]] = IntToString(i+1); // name of the node is i+1
  }
  for (i=0;i<n;i++)
    for (j=i+1;j<n;j++) {
      Edge e = g.addEdge(V[i],V[j]);  // generate an edge
      weight[e] = sqrt(pow(px[V[i]]-px[V[j]],2) + pow(py[V[i]]-py[V[j]],2));
    }
  delete[] V;
  return(true);
}
Ejemplo n.º 4
0
// To read list of nodes in the format: <node_name>  <double1>  <double2>
void ReadListGraphNodes(ListGraph &g,int nnodes,ifstream & ifile,
#if __cplusplus >= 201103L
    std::unordered_map<string,Node> & string2node,
#else
    std::tr1::unordered_map<string,Node> & string2node,
#endif
			   NodeStringMap &vname,
			   NodePosMap  &posx,
			   NodePosMap  &posy)
{ string STR;  Node u,v;  string token;
  for (int i=0;i<nnodes;i++) {
    getline(ifile,STR);
    if (ifile.eof()) {cout<<"Reached unexpected end of file.\n";exit(0);}
    while (STR=="") getline(ifile,STR);
    { istringstream ins; // Declare an input string stream.
      ins.str(STR);        // Specify string to read.
      for (int p=0; getline(ins, token, ' ') ; p++) {
	if (p==0) {   // For example, to read:   node_name   posx   posy
	  auto test = string2node.find(token);
	  if (test!=string2node.end()){cout<<"ERROR: Repeated node: "<<token<<endl;exit(0);}
	  v = g.addNode(); string2node[token] = v; vname[v] = token;
	  posx[v]=DBL_MAX;  posy[v]=DBL_MAX; }
	else if (p==1) { posx[v] = atof(token.c_str());}
	else if (p==2) { posy[v] = atof(token.c_str());}
      }}
  }
}
Ejemplo n.º 5
0
int ViewGomoryHuTree(ListGraph &g,
		     NodeStringMap& vname,
		     GomoryHu<ListGraph,
		     EdgeValueMap > &ght,
		     double threshold,
		     string text)
{
  ListGraph T;
  NodeNodeMap map(g);
  Edge te;
  EdgeStringMap tename(T);  // name of T edges
  NodeStringMap tvname(T);  // name of T nodes
  NodeColorMap tvcolor(T);   // color of the vertices
  EdgeColorMap tecolor(T);  // color of the edges
  
  for (NodeIt v(g); v != INVALID; ++v) {
    map[v] = T.addNode();
    tvname[map[v]] = vname[v];
    tvcolor[map[v]] = BLACK;
  }
  for (NodeIt u(g); u != INVALID; ++u) {
    if ((g).id(ght.predNode(u))==-1) continue;
    te = T.addEdge(map[u], map[ght.predNode(u)]);
    tename[te] = DoubleToString(ght.predValue(u));
    if (ght.predValue(u)<threshold-MY_EPS)
      tecolor[te] = RED;
    else
      tecolor[te] = BLUE;
  }
  return(ViewListGraph(g,tvname,tename,tvcolor,tecolor,text));
}
Ejemplo n.º 6
0
int ViewGomoryHuTree(ListGraph &g,
		     NodeStringMap &vname,
		     NodePosMap &px,  // xy-coodinates for each node
		     NodePosMap &py,  // 
		     GomoryHu<ListGraph, EdgeValueMap > &ght,
		     string text)
{
  ListGraph T;
  NodeNodeMap map(g);
  Edge te;
  EdgeStringMap tename(T);  // name of T edges
  EdgeValueMap teweight(T);  // name of T edges
  NodeStringMap tvname(T);  // name of T nodes
  NodePosMap tpx(T);  // xy-coodinates for each node
  NodePosMap tpy(T);  // 
  NodeColorMap tvcolor(T);   // color of the vertices
  EdgeColorMap tecolor(T);  // color of the edges
  
  for (NodeIt v(g); v != INVALID; ++v) {
    map[v] = T.addNode();
    tvname[map[v]] = vname[v];
    tvcolor[map[v]] = WHITE;
    tpx[map[v]] = px[v];
    tpy[map[v]] = py[v];
  }
  for (NodeIt u(g); u != INVALID; ++u) {
    if ((g).id(ght.predNode(u))==-1) continue;
    te = T.addEdge(map[u], map[ght.predNode(u)]);
    tename[te] = DoubleToString(ght.predValue(u));
    teweight[te] = ght.predValue(u);
    tecolor[te] = BLUE;
  }
  return(ViewListGraph(T,tvname,tename,tpx,tpy,tvcolor,tecolor,text));
}
Ejemplo n.º 7
0
// Generate a triangulated ListGraph, building the Delaunay
// triangulation of random points
// Uses the geompack program, available in
// http://people.sc.fsu.edu/~jburkardt/cpp_src/geompack/geompack.html
bool GenerateTriangulatedListGraph(ListGraph &g, // return with generated graph
			  NodeStringMap &vname, // return with name of the nodes
			  NodePosMap& px, // return with x-position of the nodes
			  NodePosMap& py, // return with y-position of the nodes
			  EdgeValueMap& weight, // return with weight of edges
			  int n, // number of nodes 
			  double SizeX, // coordinate x is a random number in [0,SizeX)
			  double SizeY) // coordinate y is a random number in [0,SizeY)
{
  int i; // n=number of nodes
  int ntri; // number of Delaunay triangles
  Node *V = new Node[n];
  double *p = new double[2*n+2];// node coodinates are (x;y) = ( p[2*i] ; p[2*i+1] )
  int *tri = new int[6*n]; // Each 3 elements are the indexes of a triangle
  int *tri_nabe = new int[6*n];
  
  if ((V==NULL)||(p==NULL)||(tri==NULL)||(tri_nabe==NULL)){
    cout << "Memory allocation error, number of nodes " << n << " too large\n";
    exit(0);}

  for (i=0;i<n;i++) {
    V[i] = g.addNode();    // gera um vértice nó do grafo 
    px[V[i]] = SizeX*drand48();  // nodes are random points
    py[V[i]] = SizeY*drand48();
    p[2*i]   = px[V[i]];
    p[2*i+1] = py[V[i]];
    vname[V[i]] = IntToString(i+1);  // name of the node is i+1
  }
  if (r8tris2 ( n, p, &ntri, tri,  tri_nabe )) {  printf("ERROR\n");Pause(); }
  for (i=0;i<ntri;i++) { 
    int a,b,c;
    a = tri[3*i]-1; b = tri[3*i+1]-1; c = tri[3*i+2]-1;
    // each triangle if formed with nodes  V[a] , V[b] , V[c]
    // insert edges without duplications
    if ((findEdge(g,V[a],V[b])==INVALID) && (findEdge(g,V[b],V[a])==INVALID)){
      Edge e = g.addEdge(V[a],V[b]);  
      weight[e] = sqrt(pow(px[V[a]]-px[V[b]],2) + pow(py[V[a]]-py[V[b]],2));
    }
    if ((findEdge(g,V[a],V[c])==INVALID)  && (findEdge(g,V[c],V[a])==INVALID)){
      Edge e = g.addEdge(V[a],V[c]);  
      weight[e] = sqrt(pow(px[V[a]]-px[V[c]],2) + pow(py[V[a]]-py[V[c]],2));
    }
    if ((findEdge(g,V[b],V[c])==INVALID) && (findEdge(g,V[c],V[b])==INVALID)) {
      Edge e = g.addEdge(V[b],V[c]);  
      weight[e] = sqrt(pow(px[V[b]]-px[V[c]],2) + pow(py[V[b]]-py[V[c]],2));
    }
  }
  delete[] V;
  delete[] p;
  delete[] tri;
  delete[] tri_nabe;
  return(true);
}
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;
    
 }
Ejemplo n.º 9
0
bool ReadEuclideanListGraph(string filename,
			    ListGraph &g,
			    NodeStringMap & vname,
			    EdgeValueMap  & custo,
			    NodePosMap    & posx,
			    NodePosMap    & posy,
                NodeBoolMap& is_terminal)
{
  int i,n,m, terminal;
  Node nu,nv;
  Edge a;
  char nomev[100];
  Node v;
  double px,py;
  
  ifstream ifile;  ifile.open(filename.c_str());  if (!ifile) return(false);
  PulaBrancoComentario(ifile);
  // format: <number_of_nodes>   -1
  // The value -1 is to indicate that there is no edge/arc, as edge weights
  // are given by the euclidean distance
  ifile >> n;    ifile >> m;
  if (m!=-1) {
    printf("Wrong format in the euclidean graph of file %s.\n",filename.c_str());
    return(false);
  }
  for (i=0;i<n;i++) {
    ifile >> nomev;  ifile >> px; ifile >> py; ifile >> terminal;
    v = g.addNode();    vname[v] = nomev;    posx[v] = px;    posy[v] = py;
      if(terminal == 0) is_terminal[v] = false;
      else is_terminal[v] = true;
  }

  for (NodeIt v(g); v!=INVALID; ++v) {
    NodeIt u(g);
    u=v;
    for (++u; u!=INVALID; ++u) {
      a = g.addEdge(u,v);
      custo[a] = sqrt((posx[u]-posx[v])*(posx[u]-posx[v]) + 
		      (posy[u]-posy[v])*(posy[u]-posy[v]));
    }
  }
  ifile.close();
  return(true);
}
Ejemplo n.º 10
0
//指定一些特殊分支,要求搜索一条路径时尽可能多的通过这些特殊分支
//例如:搜索一条串联通风路径(通过多个用风地点的一条路径)
//采用二分匹配实现失败!!!
static bool MaxKeyEdgePass_Match(Digraph& dg, EdgeArray& airEdges, Digraph::Node s, Digraph::Node t, EdgeArray& mpp)
{
    EdgeArray p;
    if(!GraphUtils::DFS_Path(dg, s, t, p)) return false;

    typedef Digraph::NodeMap<Digraph::Node> DDMap;
    DDMap ddm(dg, INVALID);

    NodeArray left, right;
    left.push_back(s); right.push_back(t);
    for(size_t i=0;i<airEdges.size();i++)
    {
        Digraph::Arc e = airEdges[i];
        Digraph::Node u = dg.source(e);
        Digraph::Node v = dg.target(e);

        p.clear();
        bool ret = GraphUtils::DFS_Path(dg, v, t, p);
        if(!ret) continue;

        p.clear();
        ret = GraphUtils::DFS_Path(dg, s, u, p);
        if(!ret) continue;

        left.push_back(v); right.push_back(u);
    }
    //cout<<"left="<<left.size()<<" right="<<right.size()<<endl;

    ListGraph g;
    ListGraph::NodeMap<Digraph::Node> udm(g);
    typedef std::vector<ListGraph::Node> UNodeArray;
    UNodeArray left_nodes, right_nodes;
    typedef std::map<Digraph::Node, ListGraph::Node> DUMap;
    DUMap dum;

    //添加节点
    for(size_t i=0;i<left.size();i++)
    {
        Digraph::Node u = left[i];
        ListGraph::Node uu = g.addNode();
        udm[uu] = u; left_nodes.push_back(uu);
        //cout<<dg.id(u)<< " ";
    }
    //cout<<endl;
    for(size_t i=0;i<right.size();i++)
    {
        Digraph::Node u = right[i];
        ListGraph::Node uu = g.addNode();
        udm[uu] = u; right_nodes.push_back(uu);
        //cout<<dg.id(u)<<" ";
    }
    //cout<<endl;
    for(size_t i=0;i<right.size();i++)
    {
        Digraph::Node u = right[i];
        ListGraph::Node uu = g.addNode();
        udm[uu] = u; left_nodes.push_back(uu);
        //cout<<dg.id(u)<< " ";
    }
    //cout<<endl;
    for(size_t i=0;i<left.size();i++)
    {
        Digraph::Node u = left[i];
        ListGraph::Node uu = g.addNode();
        udm[uu] = u; right_nodes.push_back(uu);
        //cout<<dg.id(u)<< " ";
    }
    //cout<<endl;
    //添加分支
    for(size_t i=0;i<left_nodes.size();i++)
    {
        ListGraph::Node uv = left_nodes[i];

        for(size_t j=0;j<right_nodes.size();j++)
        {
            ListGraph::Node uu = right_nodes[j];

            Digraph::Node v = udm[uv];
            Digraph::Node u = udm[uu];
            if(u == v) continue;

            p.clear();
            if(GraphUtils::DFS_Path(dg, v, u, p))
            {
                //ListGraph::Node uv = left_nodes[i];
                //ListGraph::Node uu = right_nodes[j];
                ListGraph::Edge e = g.addEdge(uu,uv);
                //cout<<"二分图:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl;
            }
        }
    }
    //二分图最大匹配
    MaxMatching<ListGraph> mm(g);
    mm.run();

    //cout<<"分支数:"<<countEdges(g)<<" 匹配数:"<<mm.matchingSize()<<endl;
    for(ListGraph::EdgeIt e(g);e!=INVALID;++e)
    {
        if(mm.matching(e))
        {
            ListGraph::Node du = g.u(e);
            ListGraph::Node dv = g.v(e);
            Digraph::Node u = udm[du];
            Digraph::Node v = udm[dv];
            //cout<<"匹配:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl;
            if(ddm[u] != INVALID && ddm[v] == INVALID)
            {
                ddm[v] = u;
                //cout<<" v"<<dg.id(v)<<"-->v"<<dg.id(u) <<"  v"<<dg.id(u)<<"-->"<<dg.id(ddm[u])<<endl;
            }
            else if(ddm[v] != INVALID && ddm[u] == INVALID)
            {
                ddm[u] = v;
                //cout<<" v"<<dg.id(v)<<"-->v"<<dg.id(ddm[v]) <<"  v"<<dg.id(u)<<"-->"<<dg.id(v)<<endl;
            }
        }
    }

    NodeArray node_path;
    Digraph::Node u = s;
    bool ret = true;
    while(u != t)
    {
        Digraph::Node v = ddm[u];
        //cout<<dg.id(u)<<"->"<<endl;
        if(v == INVALID)
        {
            //cout<<"错误"<<endl;
            ret = false;
            break;
        }
        //cout<<" ->"<<dg.id(v)<<" "<<endl;
        node_path.push_back(v);
        u = v;
    }
    if(ret)
    {
        u = s;
        for(size_t i=0;i<node_path.size();i++)
        {
            Digraph::Node v = node_path[i];
            GraphUtils::DFS_Path(dg, u, v, mpp);
            u = v;
        }
    }
    return ret;
}
Ejemplo n.º 11
0
int Steiner::steiner(const set<ListGraph::Node> terminals)
{
	if (this->s != 0) delete this->s;
	this->s = new ListGraph();
	if (this->sweight != 0) delete this->sweight;
	this->sweight = new ListGraph::EdgeMap<int>(*this->s);
	
	// perform dijkstra for every terminal
	ListGraph::NodeMap<Dijkstra*> dijk(this->g);
	for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it)
	{
		dijk[*it] = new Dijkstra(this->g, this->weight);
		dijk[*it]->dijkstra(*it);
	}

	// build intermediate graph
	ListGraph intermediate;
	ListGraph::EdgeMap<int> iweight(intermediate);
	map<ListGraph::Node, ListGraph::Node> imapper;
	
	for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it)
	{
		ListGraph::Node n = intermediate.addNode();
		imapper[n] = *it;
	}
	for (ListGraph::NodeIt it1(intermediate); it1 != INVALID; ++it1)
	{
		ListGraph::NodeIt it2 = it1;
		for (++it2; it2 != INVALID; ++it2)
		{
			ListGraph::Edge e = intermediate.addEdge(it1, it2);
			iweight[e] = (*dijk[imapper[it1]]->dist)[imapper[it2]];
		}
	}
	
	// compute mst
	MST mst(intermediate, iweight);
	mst.prim();
//	Kruskal mst(intermediate, iweight);
//	mst.kruskal();

	// build final graph
	map<ListGraph::Node, ListGraph::Node> smapper;
	for (set<ListGraph::Edge>::iterator it = mst.mst->begin(); it != mst.mst->end(); ++it)
	{ // for each edge in the mst
		// add end nodes to graph
		ListGraph::Node u = imapper[intermediate.u(*it)];
		if (smapper.count(u) == 0) smapper[u] = this->s->addNode();
		ListGraph::Node v = imapper[intermediate.v(*it)];
		if (smapper.count(v) == 0) smapper[v] = this->s->addNode();

		ListGraph::Node last = v;
		ListGraph::Node cur = v;
		do
		{ // walk through path
			cur = (*dijk[u]->pred)[cur];
			if (smapper.count(cur) == 0) smapper[cur] = this->s->addNode();
			// add edge to graph, if not already existing
			if (findEdge(*this->s, smapper[last], smapper[cur]) == INVALID)
			{
				ListGraph::Edge e = this->s->addEdge(smapper[last], smapper[cur]);
				(*this->sweight)[e] = (*dijk[u]->dist)[last] - (*dijk[u]->dist)[cur];
			}
			last = cur;
		}
		while (cur != u);
	}
	
	// compute overall weight
	int overallw = 0;
	for (ListGraph::EdgeIt e(*this->s); e != INVALID; ++e)
	{
		overallw += (*this->sweight)[e];
	}
	
	// clean up dijkstras
	for (set<ListGraph::Node>::iterator it = terminals.begin(); it != terminals.end(); ++it)
	{
		delete dijk[*it];
	}

	return overallw;
}
Ejemplo n.º 12
0
    void callback()
    { // --------------------------------------------------------------------------------
    // get the correct function to obtain the values of the lp variables
    if  (where==GRB_CB_MIPSOL) // if this condition is true, all variables are integer
        {solution_value = &subtourelim::getSolution;}
    else if ((where==GRB_CB_MIPNODE) &&  
        (getIntInfo(GRB_CB_MIPNODE_STATUS)==GRB_OPTIMAL))// node with optimal fractional solution
        {solution_value = &subtourelim::getNodeRel;}
    else return; // return, as this code do not take advantage of the other options
    // --------------------------------------------------------------------------------
    // Stores the edges with fractional values and integer values
    vector<Edge> FracEdges,OneEdges;
    // produces a subgraph h of g, with edges e with x[e]==1 
    // contracted, so we can apply Gomory-Hu tree in a small graph
    ListGraph::EdgeMap<bool> one_filter(tsp.g, false); // start without any edge
    ListGraph::EdgeMap<bool> non_zero_filter(tsp.g, false); // start without any edge
    for (EdgeIt e(tsp.g); e != INVALID; ++e) {
        if ((this->*solution_value)(x[e]) > 1-MY_EPS)
            OneEdges.push_back(e); // stores the edges with x[e]==1
        else if ((this->*solution_value)(x[e]) > MY_EPS)
            FracEdges.push_back(e); // includes edges with 0 < x[e] < 1
    }// define the subgraph with edges that have x[e]==1

    try {
        // --------------------------------------------------------------------------------
        // Use union-find to contract nodes (to obtain graph where each componente of g is contracted)
        //for (int i=0;i<tsp.NNodes;i++) UFIndexToNode[i]=INVALID;
        ListGraph::NodeMap<int> aux_map(tsp.g);
        UnionFind<ListGraph::NodeMap<int> > UFNodes(aux_map);
        for (NodeIt v(tsp.g); v!=INVALID; ++v) UFNodes.insert(v);
        for (vector<Edge>::iterator e_it=OneEdges.begin(); e_it != OneEdges.end(); ++e_it)
            UFNodes.join(tsp.g.u(*e_it),tsp.g.v(*e_it));// No problem if they are in a same component
        // --------------------------------------------------------------------------------
        // Put in a separate set all edges that are not inside a component 
        vector<Edge> CrossingEdges;
        for (EdgeIt e(tsp.g); e != INVALID; ++e) 
        if (UFNodes.find(tsp.g.u(e)) != UFNodes.find(tsp.g.v(e)))
            CrossingEdges.push_back(e);
        // --------------------------------------------------------------------------------
        // Generate an inverted list UFIndexToNode to find the node that represents a component
        vector<bool> ComponentIndex(tsp.NNodes);
        vector<Node> Index2h(tsp.NNodes);
        for(int i=0;i<tsp.NNodes;i++) ComponentIndex[i]=false;
        for (NodeIt v(tsp.g); v!=INVALID; ++v) ComponentIndex[UFNodes.find(v)]=true;
        // --------------------------------------------------------------------------------
        // Generate graph of components, add one node for each component and edges
        ListGraph h;
        EdgeValueMap h_capacity(h); 
        for(int i=0;i<tsp.NNodes;i++)  // add nodes to the graph h
            if (ComponentIndex[i]) Index2h[i]=h.addNode(); 
        for (vector<Edge>::iterator e_it=FracEdges.begin(); e_it != FracEdges.end(); ++e_it){
            Node  u = tsp.g.u(*e_it),              v = tsp.g.v(*e_it),
            hu = Index2h[UFNodes.find(u)],   hv = Index2h[UFNodes.find(v)];
            Edge a = h.addEdge(hu , hv );         // add edges to the graph h
            h_capacity[a] = (this->*solution_value)(x[*e_it]);
        }
        // create a map to terminals
        NodeBoolMap HasTerminal(h);
        for (NodeIt uit(tsp.g); uit!=INVALID; ++uit)
        {
            // if it is not a station
            if(!postos[uit]) 
            {
                HasTerminal[Index2h[UFNodes.find(uit)]] = true;
            }
        }
        // add the source to the 'terminal'
        HasTerminal[Index2h[UFNodes.find(source)]] = true;
        // --------------------------------------------------------------------------------
        GomoryHu<ListGraph, EdgeValueMap> ght(h, h_capacity);   ght.run();
        // The Gomory-Hu tree is given as a rooted directed tree. Each node has
        // an arc that points to its father. The root node has father -1.
        // Remember that each arc in this tree represents a cut and the value of
        // the arc is the weight of the corresponding cut. So, if an arc has weight
        // less than 2, then we found a violated cut and in this case, we insert the
        // corresponding constraint.

        NodeBoolMap cutmap(h);
        for (NodeIt u(h); u != INVALID; ++u) {
            GRBLinExpr expr = 0;
            if (ght.predNode(u)==INVALID) continue; // skip the root node
            if (ght.predValue(u) > 2.0 - MY_EPS) continue; // value of the cut is good
            
            // this cut violate this conditions
            // check if there is a terminal in both components
            if (HasTerminal[u] && HasTerminal[ght.predNode(u)])
            {
                ght.minCutMap(u, ght.predNode(u), cutmap);  // now, we have a violated cut
            
                // Percorre as arestas que cruzam alguma componente e insere as que pertencem ao corte
                for (vector<Edge>::iterator e_it=CrossingEdges.begin();e_it!=CrossingEdges.end();++e_it){
                    Node u=tsp.g.u(*e_it), v=tsp.g.v(*e_it),
                    hu = Index2h[UFNodes.find(u)], hv=Index2h[UFNodes.find(v)];
                    if (cutmap[hu] != cutmap[hv])
                    expr += x[*e_it];
                }
                addLazy( expr >= 2 );
            }
        }

        // Insere a restricao de sub caminho -------------------------------
        // -----------------------------------------------------------------
        // Mapeia as arestas da solucao
        int uncovered = 0;
        EdgeBoolMap covered(tsp.g, false);
        EdgeBoolMap active(tsp.g, false);
        for (EdgeIt a(tsp.g); a!=INVALID; ++a)
        {
            if (getSolution(x[a]) > 1 - MY_EPS)
            {
                active[a] = true;
                uncovered++;
            }
            else
            {
                active[a] = false;
            }
        }
        
        // -----------------------------------------------------------------
        // Percorre os caminhos e insere as restricoes de consumo
        GRBLinExpr expr = 0;
        Node u = source;
        bool changed = false;
        while (uncovered > 0)
        {
            // u := vertice atual
            // v := vertice destino
            // a := arco percorrido
            for (ListGraph::IncEdgeIt ait(tsp.g,u); ait!=INVALID; ++ait)
            {
                // verifica se o arco esta na solucao
                Edge a(ait);
                if (active[a] && !covered[a])
                {
                    // soma a distancia percorrida
                    changed = true;
                    expr += x[a]*tsp.weight[a];
                    
                    // verifica se o node destino e um posto
                    Node v = tsp.g.v(a);
                    if (u == v) 
                    {
                        v = tsp.g.u(a);
                    }
                    if (postos[v])
                    {
                        // se for um posto, termina aqui uma restricao de consumo
                        addLazy( expr <= delta);
                        expr = 0;
                    }
                    
                    // atualiza o valor do vertice atual e diminui as arestas
                    // que ainda nao foram cobertas
                    u = v;
                    covered[a] = true;
                    uncovered--;
                    break;                        
                }
            }

            // check the changed
            if (changed) 
            {
                changed = false;
            }
            else // it is a dead end 
            {
                break;
            }
        }
        // cout << "TERMINANDO CALLBACK" << endl;
    } catch (...) {
      cout << "Error during callback..." << endl;
    }
  }
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
void IMFT<Ptr>::twoFrameCorresponding(vector<ListGraph::Node> vecUFrame, vector<ListGraph::Node> vecVFrame)
{
    if(m_isDebug)   printf("2-Frame Corresponding : # F1 - %d, # F2 - %d\n", vecUFrame.size(), vecVFrame.size());
    // make graph, weight map
    ListGraph g;
    ListGraph::NodeMap<V> gNodeMap(g);
    ListGraph::EdgeMap<double> gEdgeMap(g);

    // make nodes of UFrame : save node id of UFrame
    for(int i=0;i<vecUFrame.size();i++){
        ListGraph::Node n = g.addNode();
        V v;
        v.id = m_g.id(vecUFrame.at(i));
        v.ptr = (*m_gNodeMap)[vecUFrame.at(i)].ptr;
        v.nFrame = 1;
        gNodeMap[n] = v;
    }
    // make nodes of VFrame : save node id of VFrame
    for(int i=0;i<vecVFrame.size();i++){
        ListGraph::Node n = g.addNode();
        V v;
        v.id = m_g.id(vecVFrame.at(i));
        v.ptr = (*m_gNodeMap)[vecVFrame.at(i)].ptr;
        v.nFrame = 2;
        gNodeMap[n] = v;

        // connection
        for(ListGraph::NodeIt pn(g); pn != INVALID; ++pn){
            if(gNodeMap[pn].nFrame != v.nFrame){
                double weight = gain(gNodeMap[pn], v);
                gEdgeMap[g.addEdge(pn,n)] = weight;

                //                ListGraph::Edge e = g.addEdge(pn,n);
                //                gEdgeMap[e] = weight;
                //                gNodeMap[m_g.u(e)].edgeID = g.id(e);
                //                gNodeMap[m_g.v(e)].edgeID = g.id(e);
            }
        }
    }

    // maximum weighted matching
    MaxWeightedMatching<ListGraph, ListGraph::EdgeMap<double> > mwm(g, gEdgeMap);
    mwm.run();
    int wsum = mwm.matchingWeight();
    if(m_isDebug)   printf("2-Frame Max = %d\n", wsum);

    // make edges of original graph using original nodes' ids
    for(ListGraph::EdgeIt e(g); e != INVALID; ++e){
        if(mwm.matching(e)){
            int origUId = gNodeMap[g.u(e)].id;
            int origVId = gNodeMap[g.v(e)].id;
            ListGraph::Node newU, newV;
            newU = m_g.nodeFromId(origUId);
            newV = m_g.nodeFromId(origVId);
            if(m_isDebug)   printf("2-Frame Connection %d, %d nodes\n", origUId, origVId);

            double weight = gain((*m_gNodeMap)[newU], (*m_gNodeMap)[newV]);
            ListGraph::Edge e = m_g.addEdge(newU,newV);
            (*m_gEdgeMap)[e] = weight;
            (*m_gNodeMap)[m_g.u(e)].edgeID = m_g.id(e);
            (*m_gNodeMap)[m_g.v(e)].edgeID = m_g.id(e);

            // if u가 track이 없으면, track 생성하고, v도 track에 집어 넣음.
            // u가 track이 있으면, v를 그 track에 집어 넣음.
            if(cnt > m_nWindow){
                int vId = m_g.id(m_g.u(e))-1;
                if(!(*m_gNodeMap)[m_g.nodeFromId(vId)].isTrack){
                    // generate a track of vId
                    m_cntTrack ++;
                    Track track;
                    track.setNum(m_cntTrack);
                    track.putNode((*m_gNodeMap)[m_g.nodeFromId(vId)].ptr, vId, (*m_gNodeMap)[m_g.nodeFromId(vId)].nFrame);
                    (*m_gNodeMap)[m_g.nodeFromId(vId)].isTrack = 1;
                    (*m_gNodeMap)[m_g.nodeFromId(vId)].nTrack = m_cntTrack;
                    if(m_isDebug)   printf("Generate new track # %d of node %d\n", m_cntTrack, vId);
                    // add v(e) to the track
                    track.putNode((*m_gNodeMap)[m_g.v(e)].ptr, m_g.id(m_g.v(e)), (*m_gNodeMap)[m_g.v(e)].nFrame);
                    (*m_gNodeMap)[m_g.v(e)].isTrack = 1;
                    (*m_gNodeMap)[m_g.v(e)].nTrack = m_cntTrack;
                    m_tracks.push_back(track);
                }
                else{
                    // add v(e) to the track
                    for(int i=0;i<m_tracks.size();i++){
                        if(m_tracks.at(i).num() == (*m_gNodeMap)[m_g.nodeFromId(vId)].nTrack){
                            m_tracks.at(i).putNode((*m_gNodeMap)[m_g.v(e)].ptr, m_g.id(m_g.v(e)), (*m_gNodeMap)[m_g.v(e)].nFrame);
                            (*m_gNodeMap)[m_g.v(e)].nTrack = (*m_gNodeMap)[m_g.nodeFromId(vId)].nTrack;
                            (*m_gNodeMap)[m_g.v(e)].isTrack = 1;
                            if(m_isDebug)   printf("put node %d to the track %d\n", m_g.id(m_g.v(e)), (*m_gNodeMap)[m_g.v(e)].nTrack);
                            break;
                        }
                    }
                }
            }
        }
    }
}