コード例 #1
0
ファイル: alignment_lp.cpp プロジェクト: srush/clustering
void AlignmentLP::ConstructLP(SpeechSolution *proposal) {
  try {
  GRBEnv env = GRBEnv();
  GRBModel model = GRBModel(env);
  //model.set(GRB_IntAttr_ModelSense, GRB_MINIMIZE);

  // Create all the variables.
  s.resize(cs_.problems_size());
  s2.resize(cs_.problems_size());
  //position_var.resize(cs_.problems_size()); 
  // Create the hmms. 
  for (uint u = 0; u < s.size(); ++u) {
    const ClusterProblem &problem = cs_.problem(u);
    int M = problem.num_steps;
    s[u].resize(M);
    s2[u].resize(M);
    //position_var.resize(M); 
    for (int m = 0; m < M; ++m) {
      s[u][m].resize(problem.num_states);
      s2[u][m].resize(problem.num_states);

      for (uint n = 0; n < s[u][m].size(); ++n) {
        s[u][m][n].resize(cs_.num_hidden(0));
        {
          stringstream buf;
          buf << "s2_" << u << "_" << m << "_" << n;
          s2[u][m][n] = 
            model.addVar(0.0, 1.0, 0.0, 
                         VAR_TYPE, buf.str());
        }

        for (uint o = 0; o < s[u][m][n].size(); ++o) {
          s[u][m][n][o].resize(3);
          for (uint f = 0; f <= 2; ++f) {
            stringstream buf;
            buf << "s_" << u << "_" << m << "_" << n << "_" << o << "_" << f;
            double score = distances_[u]->get_distance(m, o);
            s[u][m][n][o][f] = 
              model.addVar(0.0, 1.0, score, 
                           VAR_TYPE, buf.str());
          }
        }
      }
      // position_var[u][m].resize(cs_.num_types());
      // for (uint l = 0; l < position_var[u][m].size(); ++l) {
      //   position_var[u][m][l].resize(cs_.num_hidden(0));
      //   for (uint o = 0; o < position_var[u][m][l].size(); ++o) {
      //     stringstream buf;
      //     buf << "position_" << u << "_" << m << "_" <<  l << "_" << o;
      //     position_var[u][m][l][o] =
      //       model.addVar(0.0, 1.0, 0.0, 
      //                    VAR_TYPE, buf.str());
      //   }
      // }
    }
  }
  r.resize(cs_.num_types());
  for (uint l = 0; l < r.size(); ++l) {
    r[l].resize(cs_.num_hidden(0));
    for (uint o = 0; o < r[l].size(); ++o) {
      stringstream buf;
      buf << "r_" << l << "_" << o;
      r[l][o] = 
        model.addVar(0.0, 1.0, 0.0, 
                     VAR_TYPE, buf.str());
    }
  }

  t.resize(cs_.problems_size());
  for (uint u = 0; u < t.size(); ++u) {
    const ClusterProblem &problem = cs_.problem(u);
    t[u].resize(problem.num_states);
    for (uint n = 0; n < t[u].size(); ++n) {
      t[u][n].resize(cs_.num_hidden(0));
      for (uint o = 0; o < t[u][n].size(); ++o) {
        stringstream buf;
        buf << "t_" << u << "_" << n << "_" << o;
        t[u][n][o] = 
          model.addVar(0.0, 1.0, 0.0, 
                       VAR_TYPE, buf.str());
      }
    }
  }
  model.update();
  // Make constraints.
  // Constraint for M

  // for all l, sum_q r(l,o) = 1
  for (int l = 0; l < cs_.num_types(); ++l) {
    // Sum out o's.
    GRBLinExpr sum;
    for (int o = 0; o < cs_.num_hidden(0); ++o) {
      sum += r[l][o];
    }
    // Equal to 1.
    model.addConstr(sum == 1);
  }
  cerr << "Done Constraint 1" << endl;

  // Constraint for N
  // for all m,n,o, i, s(u, m, n, o) = s(m-1, n, o, 0) +  
  // s(m-1, n, o, 1)
  
  for (int u = 0; u < cs_.problems_size(); ++u) {
    const ClusterProblem &problem = cs_.problem(u);
    int M = problem.num_steps;
    int N = problem.num_states;

    for (int m = 0; m < M; ++m) {
      for (int n = 0; n < N; ++n) {
        for (int o = 0; o < cs_.num_hidden(0); ++o) {

          if (m != 0 && n != 0) {            
            GRBLinExpr sum;
            model.addConstr(s[u][m][n][o][0] + 
                            s[u][m][n][o][2] == 
                            s[u][m - 1][n][o][0] + 
                            s[u][m - 1][n][o][1], "incoming");
          }

          if (m != M - 1 && n != N - 1) {
            model.addConstr(s[u][m][n][o][0] + 
                            s[u][m][n][o][1] == 
                            s[u][m + 1][n][o][0] + 
                            s[u][m + 1][n][o][2], "Outgoing");            
          }
          GRBLinExpr sum, sum2;
          for (int o2 = 0; o2 < cs_.num_hidden(0); ++o2) {
            sum += s[u][m][n][o2][1];
            sum2 += s[u][m][n][o2][2];
          }
          model.addConstr(s2[u][m][n] == sum, "Outgoing");
          if (m != M - 1 && n != N - 1) {
            model.addConstr(sum2 == 
                            s2[u][m + 1][n + 1], "Outgoing");
          }
        }
      }
    }
    {
      GRBLinExpr sum;
      for (int o = 0; o < cs_.num_hidden(0); ++o) {
        sum += s[u][0][0][o][1];
      }
      model.addConstr(sum == 1, "Starting");
    }
    
    {
      GRBLinExpr sum;
      for (int o = 0; o < cs_.num_hidden(0); ++o) {
        sum += s[u][problem.num_steps - 1][problem.num_states - 1][o][0];
      }
      model.addConstr(sum == 1);
    }
  }

  // Tying constraints 3.
  // forall n, o, r(y_n, o) = t(n,o)
  for (int u = 0; u < cs_.problems_size(); ++u) {
    const ClusterProblem &problem = cs_.problem(u);
    for (int n = 0; n < problem.num_states; ++n) {
      GRBLinExpr sum;
      for (int o = 0; o < cs_.num_hidden(0); ++o) {
        sum += t[u][n][o];
      }
      model.addConstr(sum == 1);
    }
    for (int n = 0; n < problem.num_states; ++n) {
      int l = problem.MapState(n);
      for (int o = 0; o < cs_.num_hidden(0); ++o) {
        model.addConstr(r[l][o] == t[u][n][o]);

        GRBLinExpr sum;
        for (int m = 0; m < problem.num_steps; ++m) {
          sum += s[u][m][n][o][1];
        }
        model.addConstr(sum == t[u][n][o]);
      }
    }
  }
  cerr << "Done Constraint 3" << endl;
  
  if (true)  {
    for (int u = 0; u < cs_.problems_size(); ++u) {
      const ClusterProblem &problem = cs_.problem(u);
      int M = problem.num_steps;
      int N = problem.num_states;
      for (int m = 0; m < M; ++m) {
        for (uint l = 0; l < r.size(); ++l) {
          vector <int> locations;
          for (int n = 0; n < N; ++n) {
            if ((int)l == problem.MapState(n)) {
              locations.push_back(n);
            }
          }

          for (int o = 0; o < cs_.num_hidden(0); ++o) {
            GRBLinExpr sum;
            for (uint occ_index = 0; occ_index < locations.size(); ++occ_index) {
              int n = locations[occ_index];
              sum += s[u][m][n][o][0] + s[u][m][n][o][1] + s[u][m][n][o][2];
            }
            //model.addConstr(position_var[u][m][l][o] == sum);
            model.addConstr(sum <= r[l][o]);
          }
        }
      }
    }
  }

  // model.addConstr(r[7][2] == 0.5);
  // model.addConstr(r[7][3] == 0.5);
  // model.addConstr(r[0][1] == 0.5);
  // model.addConstr(r[0][6] == 0.5);
  // model.addConstr(r[13][4] == 0.5);
  // model.addConstr(r[13][9] == 0.5);
  model.update();
  //model.write("temp.lp");

  // 
  // // Done!
   model.optimize();
   if (model.get(GRB_IntAttr_Status) != GRB_OPTIMAL) {
     model.computeIIS();
     model.write("temp.ilp");
   }

  vector<double> costs;
  for (uint u = 0; u < s.size(); ++u) {
    SpeechAlignment *align = proposal->mutable_alignment(u);
    const ClusterProblem &problem = cs_.problem(u);
    vector<int> *state_hidden = align->mutable_hidden_alignment();
    vector<int> *state_align = align->mutable_alignment();
    state_hidden->resize(problem.num_steps);
    state_align->resize(problem.num_steps);
    
    int M = problem.num_steps;
    int N = 0;
    for (int m = 0; m < M; ++m) {
      N = s[u][m].size();
      costs.resize(s[u][m].size());
      for (uint n = 0; n < s[u][m].size(); ++n) {
        for (uint o = 0; o < s[u][m][n].size(); ++o) {
          for (uint f = 0; f <= 2; ++f) {
            if (s[u][m][n][o][f].get(GRB_DoubleAttr_X) != 0) {
              (*state_hidden)[m] = o;
              (*state_align)[m] = problem.MapState(n);
              string position;
              if (f == 0) {
                position = "I";
              } else if (f == 1) {
                position = "B";
              } else { 
                position = "O";
              }
              cerr << "s " << m << " " << n << " " << o << " " << position << " "
                   << s[u][m][n][o][f].get(GRB_DoubleAttr_X) 
                   << " " << s[u][m][n][o][f].get(GRB_DoubleAttr_Obj) 
                   << " " << problem.MapState(n) << endl;
              costs[n] += s[u][m][n][o][f].get(GRB_DoubleAttr_X) 
                * s[u][m][n][o][f].get(GRB_DoubleAttr_Obj);
            }
          }
        }
      }
    }
    for (int n = 0; n < N; ++n) {
      cerr << n << " " << costs[n] << endl;
    }
  }


  for (uint u = 0; u < t.size(); ++u) {
    for (uint n = 0; n < t[u].size(); ++n) {
      for (uint o = 0; o < t[u][n].size(); ++o) {
        if (t[u][n][o].get(GRB_DoubleAttr_X) != 0) {
          cerr << "t " <<  n << " " << o << " " <<
            t[u][n][o].get(GRB_DoubleAttr_X) << endl;
        }
      }
    }
  }

  for (uint l = 0; l < r.size(); ++l) {
    for (uint o = 0; o < r[l].size(); ++o) {
      if (r[l][o].get(GRB_DoubleAttr_X) != 0) {
        cerr << "r " << l << " " << o << " " <<
          r[l][o].get(GRB_DoubleAttr_X) << endl;
      }
    }
  }


  } catch(GRBException e) {
    cout << "Error code = " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  } catch(...) {
    cout << "Exception during optimization" << endl;
  }
}
コード例 #2
0
ファイル: solvergurobi.cpp プロジェクト: bgrimstad/censo
// Start the optimization
SolverResult SolverGurobi::runOptimizer()
{
    if (!getInitialized())
        initialize();

    try
    {
        // Create Gurobi environment and set parameters
        GRBEnv env = GRBEnv();
        env.set(GRB_IntParam_OutputFlag, 0);

        GRBModel model = GRBModel(env);

        // Get problem info
        int numVars = constraints->getNumVariables();
        int numConstraints = constraints->getNumConstraints();

        // Get variables
        auto variables = constraints->getVariables();

        // Create array of model variables
        GRBVar vars[numVars];
        for (int i = 0; i < numVars; i++)
        {
            //vars[i] = model.addVar(0.0, 1.0, 0.0, GRB_BINARY);

            // Set variable type
            char type = GRB_CONTINUOUS;
            if (variables.at(i)->getType() == VariableType::BINARY)
            {
                type = GRB_BINARY;
            }
            else if (variables.at(i)->getType() == VariableType::INTEGER)
            {
                type = GRB_INTEGER;
            }
            vars[i] = model.addVar(variables.at(i)->getLowerBound(),
                                   variables.at(i)->getUpperBound(),
                                   variables.at(i)->getCost(),
                                   type);
        }

        // Integrate variables into model
        model.update();

        // Set starting points (does not help much...)
        for (int i = 0; i < numVars; i++)
            vars[i].set(GRB_DoubleAttr_Start, variables.at(i)->getValue());

        /*
         * Add constraints Ax <= b (or Ax = b)
         * by evaluating gradient and build A matrix
         */
        DenseVector x = DenseVector::Zero(numVars);
        DenseVector dx = constraints->evalJacobian(x);

        // Get constraint bounds
        std::vector<double> clb;
        std::vector<double> cub;
        constraints->getConstraintBounds(clb,cub);

        std::vector<int> rowGradient, colGradient;
        constraints->structureJacobian(rowGradient, colGradient);
        int nnzJacobian = constraints->getNumNonZerosJacobian();

        // Add constraints one row at the time
        for (int row = 0; row < numConstraints; row++)
        {
            // Build constraint
            GRBLinExpr expr = 0;

            // Loop through all non-zeros (inefficient)
            for (int i = 0; i < nnzJacobian; i++)
            {
                if (rowGradient.at(i) == row)
                {
                    int j = colGradient.at(i);
                    expr += dx(i)*vars[j];
                }
            }

            // Add constraint to model
            if (clb.at(row) == cub.at(row))
            {
                model.addConstr(expr, GRB_EQUAL, cub.at(row));
            }
            else
            {
                model.addConstr(expr, GRB_LESS_EQUAL, cub.at(row));
            }
        }

        // More efficient method - avoids dense matrix
//        std::vector<int> rows = {1,1,1,2,2,3,4,4,4,4,4,5};
//        std::vector<int>::iterator start,stop;
//        start = rows.begin();
//        stop = start;
//        while (start != rows.end())
//        {
//            while (stop != rows.end())
//            {
//                if (*stop == *start)
//                    ++stop;
//                else
//                    break;
//            }
//            for (std::vector<int>::iterator it = start; it != stop; ++it)
//                cout << *it << endl;

//            start = stop;
//        }

        model.update();

        assert(numVars == model.get(GRB_IntAttr_NumVars));
        assert(numConstraints == model.get(GRB_IntAttr_NumConstrs));

        // Optimize model
        model.optimize();

        // Check status
        int optimstatus = model.get(GRB_IntAttr_Status);

        if (optimstatus == GRB_INF_OR_UNBD)
        {
            model.getEnv().set(GRB_IntParam_Presolve, 0);
            model.optimize();
            optimstatus = model.get(GRB_IntAttr_Status);
        }

        // Create result object
        SolverResult result(SolverStatus::ERROR, INF, std::vector<double>(numVars,0));

        // Check Gurobi status
        if (optimstatus == GRB_OPTIMAL)
        {
            result.status = SolverStatus::OPTIMAL;

            // Get solution info
            result.objectiveValue = model.get(GRB_DoubleAttr_ObjVal);

            std::vector<double> optimalSolution;
            for (int i = 0; i < numVars; i++)
            {
                optimalSolution.push_back(vars[i].get(GRB_DoubleAttr_X));
            }

            result.primalVariables = optimalSolution;

            /*
             * Reduced costs and constraint duals are
             * only available for continuous models
             */
            std::vector<double> reducedCosts;
            std::vector<double> constraintDuals;
            if (!model.get(GRB_IntAttr_IsMIP))
            {
                for (int i = 0; i < numVars; i++)
                {
                    // Get reduced costs (related to range constraint duals)
                    reducedCosts.push_back(vars[i].get(GRB_DoubleAttr_RC));
                }

                for (int i = 0; i < numConstraints; i++)
                {
                    GRBConstr c = model.getConstr(i);
                    double pi = c.get(GRB_DoubleAttr_Pi);
                    constraintDuals.push_back(pi);
                }
            }

            result.lowerBoundDualVariables = reducedCosts;
            result.upperBoundDualVariables = reducedCosts;
            result.constraintDualVariables = constraintDuals;

            return result;
        }
        else if (optimstatus == GRB_INFEASIBLE)
        {
            result.status = SolverStatus::INFEASIBLE;
            result.objectiveValue = INF;
            // compute and write out IIS
            // model.computeIIS();
            // model.write("problem.lp");
            return result;
        }
        else if (optimstatus == GRB_UNBOUNDED)
        {
            result.status = SolverStatus::UNBOUNDED;
            result.objectiveValue = -INF;
            return result;
        }
        else
        {
            result.status = SolverStatus::ERROR;
            result.objectiveValue = INF;
            return result;
        }
    }
    catch(GRBException e)
    {
        cout << "SolverGurobi: Error code = " << e.getErrorCode() << endl;
        cout << e.getMessage() << endl;
        return SolverResult(SolverStatus::ERROR, INF, std::vector<double>(constraints->getNumVariables(),0));
    }
    catch (...)
    {
        cout << "SolverGurobi: Error during optimization!" << endl;
        return SolverResult(SolverStatus::ERROR, INF, std::vector<double>(constraints->getNumVariables(),0));
    }
}
コード例 #3
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;
    }
  }
}
コード例 #4
0
int main(int argc, char *argv[]) 
{
  int time_limit;
  char name[1000];
  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, "Emparelhamento perfeito with GUROBI");
  // name to the problem
  model.set(GRB_IntAttr_ModelSense, GRB_MAXIMIZE); // 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 == 1);
  }

  try {
    model.update(); // Process any pending model modifications.
    if (time_limit >= 0) model.getEnv().set(GRB_DoubleParam_TimeLimit,time_limit);

    model.update(); // Process any pending model modifications.
    model.write("model.lp");
    system("cat model.lp");

    model.optimize();

    double soma=0.0;
    int i = 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];
	cout << "Achei, x("<< vname[g.u(e)] << " , " << vname[g.v(e)] << ") = " << lpvar[e] <<"\n";
	tsp.BestCircuit[i] = g.u(e);
	tsp.BestCircuit[i+1] = g.v(e);
	i = i+2;
	
      }
    }

    cout << "Solution cost = "<< soma << endl;
    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;
    }
  }
}