10
$\begingroup$

I am writing a small wrapper around Gurobi and Cplex so that the models I write are solver independent. I'm very familiar with Gurobi but I'm very new to Cplex and I'm having trouble replicating certain api calls that I use very frequently.

Specifically I'm having trouble figuring out how to pass the sense to the Cplex API:

std::shared_ptr<Constraint> Model::addConstr(const std::vector<std::shared_ptr<Variable>>& vars,
      const std::vector<double>& coeffs, char sense,
      double rhs, const std::string& name) 
#ifdef GUROBI   
    GRBLinExpr expr;
    std::vector<GRBVar> grb_vars;
    for(auto var : vars) {
      grb_vars.push_back(*(var->getGRBVar()));
    }
    expr.addTerms(&coeffs[0], &grb_vars[0], (int) vars.size());
    GRBConstr constraint = _grb_model->addConstr(expr, sense, rhs, name);
    std::shared_ptr<GRBConstr> grb_constr_shared = std::make_shared<GRBConstr>(constraint);
    return std::make_shared<Constraint>(grb_constr_shared);
#elif defined CPLEX
  // do exactly the same process for cplex
  IloExpr expr(_cplex_env);
  for(int i = 0; i < vars.size(); ++i) {
    expr += coeffs[i] * vars[i];  
  }
  // this line below doesn't work -- I don't know how to pass the sense of
  // the constraint. I'd like to avoid using a switch statement if possible..
  IloConstraint constraint = _cplex_model.add(expr, sense, rhs);
#endif
}

And I'm having trouble figuring out how to pass the coefficient for a variable in the objective. I'd like to be able to do this on creation of the variable (or at least immediately after creating the variable) so that I can have similar functionality to gurobi.

std::shared_ptr<Variable> Model::addVar(double lb, double ub, double obj,
      char var_type, std::string name) {
#ifdef GUROBI
    GRBVar grb_var = _grb_model->addVar(lb, ub, obj, var_type, std::move(name));
    std::shared_ptr<GRBVar> grb_var_shared = std::make_shared<GRBVar>(grb_var);
    return std::make_shared<Variable>(grb_var_shared);
#elif defined CPLEX
  // do the same process for CPLEX and return std::make_shared<Variable>(cplex_var_shared);
    // this line defines the variable but doesn't set its coeff in the
    // objective function -- how do I set the variable's objective coefficient?
    IloNumVar var(*_cplex_env, lb, ub, IloNumVar::Int, name.c_str());

#endif
  }

Edit: stackoverflow link: https://stackoverflow.com/questions/58107655/specify-the-sense-of-a-constraint-in-cplex

I'll update both posts if I receive an answer in either community.

$\endgroup$
  • $\begingroup$ Hi, and welcome to OR.SE! I've removed "cross post from Stack Overflow" from the title of your question. That info would probably be better in the body of your question, as well as a link to your question on SO. But in general, cross posting is discouraged on SE. $\endgroup$ – LarrySnyder610 Sep 26 '19 at 0:01
  • $\begingroup$ Thanks Larry, good to know for the future. Though I do think this question falls in the "grey area" between the two communities. $\endgroup$ – Connor Sep 26 '19 at 1:08
  • $\begingroup$ Oh, definitely. I think it fits perfectly here on OR.SE, and it fits fine on SO too. But posting it on both sites simultaneously can cause duplication of work among the answerers, so it's best to avoid it. $\endgroup$ – LarrySnyder610 Sep 26 '19 at 1:36
7
$\begingroup$

For specifying constraint direction, look to the various IloRange constructors. You can specify both a lower and upper bound (for constraints of the form $b_0 \le a'x \le b_1$, or use a constructor that either defaults the lower bound to $-\infty$ or defaults the upper bound to $+\infty$.

For adding objective terms, you have at least a couple of options I can think of. You can create a linear expression for the objective first, then add terms to it as the variables are created, and then add the completed expression as an objective. Alternatively, you can store the coefficients in a one-dimensional double array (and, if not already doing so, the variables in another vector) as the variables are generated, then use that vector to create the objective. Check out IloScalProd for use in that approach.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.