UnicodeSet&
UnicodeSet::applyPropertyAlias(const UnicodeString& prop,
                               const UnicodeString& value,
                               UErrorCode& ec) {
    if (U_FAILURE(ec) || isFrozen()) return *this;

    // prop and value used to be converted to char * using the default
    // converter instead of the invariant conversion.
    // This should not be necessary because all Unicode property and value
    // names use only invariant characters.
    // If there are any variant characters, then we won't find them anyway.
    // Checking first avoids assertion failures in the conversion.
    if( !uprv_isInvariantUString(prop.getBuffer(), prop.length()) ||
        !uprv_isInvariantUString(value.getBuffer(), value.length())
    ) {
        FAIL(ec);
    }
    CharString pname(prop);
    CharString vname(value);

    UProperty p;
    int32_t v;
    UBool mustNotBeEmpty = FALSE, invert = FALSE;

    if (value.length() > 0) {
        p = u_getPropertyEnum(pname);
        if (p == UCHAR_INVALID_CODE) FAIL(ec);

        // Treat gc as gcm
        if (p == UCHAR_GENERAL_CATEGORY) {
            p = UCHAR_GENERAL_CATEGORY_MASK;
        }

        if ((p >= UCHAR_BINARY_START && p < UCHAR_BINARY_LIMIT) ||
            (p >= UCHAR_INT_START && p < UCHAR_INT_LIMIT) ||
            (p >= UCHAR_MASK_START && p < UCHAR_MASK_LIMIT)) {
            v = u_getPropertyValueEnum(p, vname);
            if (v == UCHAR_INVALID_CODE) {
                // Handle numeric CCC
                if (p == UCHAR_CANONICAL_COMBINING_CLASS ||
                    p == UCHAR_TRAIL_CANONICAL_COMBINING_CLASS ||
                    p == UCHAR_LEAD_CANONICAL_COMBINING_CLASS) {
                    char* end;
                    double value = uprv_strtod(vname, &end);
                    v = (int32_t) value;
                    if (v != value || v < 0 || *end != 0) {
                        // non-integral or negative value, or trailing junk
                        FAIL(ec);
                    }
                    // If the resultant set is empty then the numeric value
                    // was invalid.
                    mustNotBeEmpty = TRUE;
                } else {
                    FAIL(ec);
                }
            }
        }

        else {

            switch (p) {
            case UCHAR_NUMERIC_VALUE:
                {
                    char* end;
                    double value = uprv_strtod(vname, &end);
                    if (*end != 0) {
                        FAIL(ec);
                    }
                    applyFilter(numericValueFilter, &value, UPROPS_SRC_CHAR, ec);
                    return *this;
                }
                break;
            case UCHAR_NAME:
            case UCHAR_UNICODE_1_NAME:
                {
                    // Must munge name, since u_charFromName() does not do
                    // 'loose' matching.
                    char buf[128]; // it suffices that this be > uprv_getMaxCharNameLength
                    if (!mungeCharName(buf, vname, sizeof(buf))) FAIL(ec);
                    UCharNameChoice choice = (p == UCHAR_NAME) ?
                        U_EXTENDED_CHAR_NAME : U_UNICODE_10_CHAR_NAME;
                    UChar32 ch = u_charFromName(choice, buf, &ec);
                    if (U_SUCCESS(ec)) {
                        clear();
                        add(ch);
                        return *this;
                    } else {
                        FAIL(ec);
                    }
                }
                break;
            case UCHAR_AGE:
                {
                    // Must munge name, since u_versionFromString() does not do
                    // 'loose' matching.
                    char buf[128];
                    if (!mungeCharName(buf, vname, sizeof(buf))) FAIL(ec);
                    UVersionInfo version;
                    u_versionFromString(version, buf);
                    applyFilter(versionFilter, &version, UPROPS_SRC_PROPSVEC, ec);
                    return *this;
                }
                break;
            default:
                // p is a non-binary, non-enumerated property that we
                // don't support (yet).
                FAIL(ec);
            }
        }
    }

    else {
        // value is empty.  Interpret as General Category, Script, or
        // Binary property.
        p = UCHAR_GENERAL_CATEGORY_MASK;
        v = u_getPropertyValueEnum(p, pname);
        if (v == UCHAR_INVALID_CODE) {
            p = UCHAR_SCRIPT;
            v = u_getPropertyValueEnum(p, pname);
            if (v == UCHAR_INVALID_CODE) {
                p = u_getPropertyEnum(pname);
                if (p >= UCHAR_BINARY_START && p < UCHAR_BINARY_LIMIT) {
                    v = 1;
                } else if (0 == uprv_comparePropertyNames(ANY, pname)) {
                    set(MIN_VALUE, MAX_VALUE);
                    return *this;
                } else if (0 == uprv_comparePropertyNames(ASCII, pname)) {
                    set(0, 0x7F);
                    return *this;
                } else if (0 == uprv_comparePropertyNames(ASSIGNED, pname)) {
                    // [:Assigned:]=[:^Cn:]
                    p = UCHAR_GENERAL_CATEGORY_MASK;
                    v = U_GC_CN_MASK;
                    invert = TRUE;
                } else {
                    FAIL(ec);
                }
            }
        }
    }
    
    applyIntPropertyValue(p, v, ec);
    if(invert) {
        complement();
    }

    if (U_SUCCESS(ec) && (mustNotBeEmpty && isEmpty())) {
        // mustNotBeEmpty is set to true if an empty set indicates
        // invalid input.
        ec = U_ILLEGAL_ARGUMENT_ERROR;
    }

    if (isBogus() && U_SUCCESS(ec)) {
        // We likely ran out of memory. AHHH!
        ec = U_MEMORY_ALLOCATION_ERROR;
    }
    return *this;
}
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;
    }
  }
}
Exemple #3
0
/// Get a named view, redefining it to match the given structure
c4_View c4_Storage::GetAs(const char *description_) {
  d4_assert(description_ != 0);

  // Dec 2001: now that GetAs is being used so much more frequently, 
  // add a quick check to see whether restructuring is needed at all
  const char *q = strchr(description_, '[');
  if (q != 0) {
    c4_String vname(description_, q - description_);
    const char *d = Description(vname);
    if (d != 0) {
      c4_String desc(d);
      if (("[" + desc + "]").CompareNoCase(q) == 0)
        return View(vname);
    }
  }

  c4_Field *field = d4_new c4_Field(description_);
  d4_assert(field != 0);

  d4_assert(! *description_);

  c4_String name = field->Name();
  d4_assert(!name.IsEmpty());

  c4_Field &curr = Persist()->Root().Definition();

  c4_String newField = "," + field->Description();
  bool keep = newField.Find('[') >= 0;

  c4_String newDef;

  // go through all subfields
  for (int i = 0; i < curr.NumSubFields(); ++i) {
    c4_Field &of = curr.SubField(i);
    if (of.Name().CompareNoCase(name) == 0) {
      if (field->IsRepeating())
        newDef += newField;
      // else new is not a repeating entry, so drop this entire field

      newField.Empty(); // don't append it later on
      continue;
    }

    newDef += "," + of.Description(); // keep original field
  }

  if (keep)
  // added 19990824 ignore if deletion
    newDef += newField;
  // appends new definition if not found earlier

  delete field;

  const char *p = newDef;
  SetStructure(*p ? ++p: p); // skip the leading comma

  if (!keep)
  // 19990916: avoid adding an empty view again
    return c4_View();

  return View(name);
}
Exemple #4
0
bool SIMoutput::writeGlvS2 (const Vector& psol, int iStep, int& nBlock,
                            double time, int idBlock, int psolComps)
{
  if (psol.empty())
    return true; // No primary solution
  else if (!myVtf || !myProblem)
    return false;
  else if (myProblem->getNoSolutions() < 1)
    return true; // No patch-level primary solution

  size_t nf = myProblem->getNoFields(2);
  if (nf < 1) return true; // No secondary solution

  bool haveAsol = false;
  if (mySol)
  {
    if (this->getNoFields() == 1)
      haveAsol = mySol->hasScalarSol() > 1;
    else
      haveAsol = mySol->hasVectorSol() > 1;
  }

  bool doProject = (opt.discretization == ASM::Spline ||
                    opt.discretization == ASM::SplineC1) &&
    opt.project.find(SIMoptions::GLOBAL) != opt.project.end();

  size_t sMAX = nf;
  if (haveAsol) sMAX += nf;
  if (doProject) sMAX += nf;
  std::vector<IntVec> sID(sMAX);
  std::array<IntVec,2> vID;
  Matrix field, pdir;
  Vector lovec;

  size_t i, j, k;
  int geomID = myGeomID;
  for (i = 0; i < myModel.size(); i++)
  {
    if (myModel[i]->empty()) continue; // skip empty patches

    if (msgLevel > 1)
      IFEM::cout <<"Writing secondary solution for patch "<< i+1 << std::endl;

    // Direct evaluation of secondary solution variables

    LocalSystem::patch = i;
    myProblem->initResultPoints(time,true);
    myModel[i]->extractNodeVec(psol,myProblem->getSolution(),psolComps,0);
    this->extractPatchDependencies(myProblem,myModel,i);
    this->setPatchMaterial(i+1);
    if (!myModel[i]->evalSolution(field,*myProblem,opt.nViz))
      return false;

    myModel[i]->filterResults(field,myVtf->getBlock(++geomID));

    for (j = 1, k = 0; j <= field.rows() && k < sMAX; j++)
      if (!myVtf->writeNres(field.getRow(j),++nBlock,geomID))
        return false;
      else
        sID[k++].push_back(nBlock);

    // Write principal directions, if any, as vector fields

    size_t nPoints = field.cols();
    for (j = 0; j < 2 && myProblem->getPrincipalDir(pdir,nPoints,j+1); j++)
    {
      myModel[i]->filterResults(pdir,myVtf->getBlock(geomID));
      if (!myVtf->writeVres(pdir,++nBlock,geomID,this->getNoSpaceDim()))
        return -2;
      else
        vID[j].push_back(nBlock);
    }

    if (doProject)
    {
      // Projection of secondary solution variables (tensorial splines only)

      myProblem->initResultPoints(time);
      if (!myModel[i]->evalSolution(field,*myProblem,opt.nViz,'D'))
        return false;

      myModel[i]->filterResults(field,myVtf->getBlock(geomID));

      for (j = 1; j <= field.rows() && k < sMAX; j++)
        if (!myVtf->writeNres(field.getRow(j),++nBlock,geomID))
          return false;
        else
          sID[k++].push_back(nBlock);
    }

    if (haveAsol)
    {
      // Evaluate analytical solution variables

      if (msgLevel > 1)
        IFEM::cout <<"Writing exact solution for patch "<< i+1 << std::endl;

      const ElementBlock* grid = myVtf->getBlock(geomID);
      Vec3Vec::const_iterator cit = grid->begin_XYZ();
      field.fill(0.0);
      for (j = 1; cit != grid->end_XYZ() && haveAsol; j++, cit++)
      {
        Vec4 Xt(*cit,time);
        if (mySol->hasScalarSol() == 3 || mySol->hasVectorSol() == 3)
          haveAsol = myProblem->evalSol(lovec,*mySol->getStressSol(),Xt);
        else if (this->getNoFields() == 1)
          haveAsol = myProblem->evalSol(lovec,*mySol->getScalarSecSol(),Xt);
        else
          haveAsol = myProblem->evalSol(lovec,*mySol->getVectorSecSol(),Xt);
        if (haveAsol)
          field.fillColumn(j,lovec);
      }

      for (j = 1; j <= field.rows() && k < sMAX && haveAsol; j++)
        if (!myVtf->writeNres(field.getRow(j),++nBlock,geomID))
          return false;
        else
          sID[k++].push_back(nBlock);
    }
  }

  // Write result block identifications

  std::string vname("Principal direction P1");
  for (i = 0; i < 2; i++, vname[vname.size()-1]++)
    if (!vID[i].empty())
      if (!myVtf->writeVblk(vID[i],vname.c_str(),idBlock+i,iStep))
        return false;

  const char* prefix = haveAsol ? "FE" : nullptr;
  for (i = j = 0; i < nf && j < sMAX && !sID[j].empty(); i++, j++)
    if (!myVtf->writeSblk(sID[j],myProblem->getField2Name(i,prefix).c_str(),
                          idBlock++,iStep)) return false;

  if (doProject)
    for (i = 0; i < nf && j < sMAX && !sID[j].empty(); i++, j++)
      if (!myVtf->writeSblk(sID[j],myProblem->getField2Name(i,"Projected").c_str(),
                            idBlock++,iStep)) return false;

  if (haveAsol)
    for (i = 0; i < nf && j < sMAX && !sID[j].empty(); i++, j++)
      if (!myVtf->writeSblk(sID[j],myProblem->getField2Name(i,"Exact").c_str(),
                            idBlock++,iStep)) return false;

  return true;
}
Exemple #5
0
int SIMoutput::writeGlvS1 (const Vector& psol, int iStep, int& nBlock,
                           double time, const char* pvecName,
                           int idBlock, int psolComps, bool scalarOnly)
{
  if (psol.empty())
    return 0;
  else if (!myVtf)
    return -99;

  bool scalarEq = scalarOnly || this->getNoFields() == 1;
  size_t nVcomp = scalarEq ? 1 : this->getNoFields();
  if (nVcomp > this->getNoSpaceDim())
    nVcomp = this->getNoSpaceDim();

  bool haveXsol = false;
  if (mySol)
  {
    if (scalarEq)
      haveXsol = mySol->getScalarSol() != nullptr;
    else
      haveXsol = mySol->getVectorSol() != nullptr;
  }

  size_t nf = scalarEq ? 1 : this->getNoFields();
  size_t pMAX = haveXsol ? nf+nf : nf;
  std::vector<IntVec> sID(pMAX);
  std::array<IntVec,2> vID;
  Matrix field;
  Vector lovec;

  size_t i, j, k;
  int geomID = myGeomID;
  for (i = 0; i < myModel.size(); i++)
  {
    if (myModel[i]->empty()) continue; // skip empty patches

    if (msgLevel > 1)
      IFEM::cout <<"Writing primary solution for patch "<< i+1 << std::endl;

    // Evaluate primary solution variables

    myModel[i]->extractNodeVec(psol,lovec,psolComps,0);
    if (!myModel[i]->evalSolution(field,lovec,opt.nViz))
      return -1;

    myModel[i]->filterResults(field,myVtf->getBlock(++geomID));

    if (!scalarOnly && (nVcomp > 1 || !pvecName))
    {
      // Output as vector field
      if (!myVtf->writeVres(field,++nBlock,geomID,nVcomp))
        return -2;
      else
        vID[0].push_back(nBlock);
    }
    for (j = 1, k = 0; j <= field.rows() && k < pMAX; j++)
      if (!myVtf->writeNres(field.getRow(j),++nBlock,geomID))
        return -3;
      else
        sID[k++].push_back(nBlock);

    if (haveXsol)
    {
      if (msgLevel > 1)
        IFEM::cout <<"Writing exact solution for patch "<< i+1 << std::endl;

      // Evaluate exact primary solution

      const ElementBlock* grid = myVtf->getBlock(geomID);
      Vec3Vec::const_iterator cit = grid->begin_XYZ();
      field.fill(0.0);
      if (scalarEq)
      {
        const RealFunc& pSol = *mySol->getScalarSol();
        for (j = 1; cit != grid->end_XYZ() && haveXsol; j++, ++cit)
          field(1,j) = pSol(Vec4(*cit,time));
      }
      else
      {
        const VecFunc& pSol = *mySol->getVectorSol();
        for (j = 1; cit != grid->end_XYZ() && haveXsol; j++, ++cit)
          field.fillColumn(j,pSol(Vec4(*cit,time)).ptr());
        if (mySol->getScalarSol())
        {
          cit = grid->begin_XYZ();
          const RealFunc& sSol = *mySol->getScalarSol();
          for (j = 1; cit != grid->end_XYZ() && haveXsol; j++, ++cit)
            field(field.rows(),j) = sSol(Vec4(*cit,time));
        }
      }

      for (j = 1; j <= field.rows() && k < pMAX && haveXsol; j++)
        if (!myVtf->writeNres(field.getRow(j),++nBlock,geomID))
          return -3;
        else
          sID[k++].push_back(nBlock);

      if (!myVtf->writeVres(field,++nBlock,geomID,nVcomp))
        return -2;
      else
        vID[1].push_back(nBlock);
    }
  }

  // Write result block identifications

  bool ok = true;
  std::string pname(pvecName ? pvecName : "Solution");
  for (i = 0; i < 2 && ok; i++)
    if (!vID[i].empty())
    {
      std::string vname(i == 1 ? "Exact " + pname : pname);
      if (pvecName)
        ok = myVtf->writeVblk(vID[i],vname.c_str(),idBlock+i,iStep);
      else
        ok = myVtf->writeDblk(vID[i],vname.c_str(),idBlock+i,iStep);
    }

  if (idBlock <= (int)this->getNoSpaceDim())
    idBlock = this->getNoSpaceDim()+1; // Since we might have written BCs above

  std::vector<std::string> xname;
  if (haveXsol) xname.reserve(nf);
  if (nf > 1) pname += "_w";
  for (i = j = 0; i < nf && j < pMAX && !sID[j].empty() && ok; i++)
  {
    if (myProblem && (!pvecName || nf > nVcomp))
      pname = myProblem->getField1Name(i);
    else if (nf > 1)
      (*pname.rbegin()) ++;
    ok = myVtf->writeSblk(sID[j++],pname.c_str(),idBlock++,iStep);
    if (haveXsol) xname.push_back("Exact " + pname);
  }

  for (i = 0; i < xname.size() && j < pMAX && !sID[j].empty() && ok; i++)
    ok = myVtf->writeSblk(sID[j++],xname[i].c_str(),idBlock++,iStep);

  return ok ? idBlock : -4;
}
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;
    }
  }
}