c++ - 在 CPLEX 中指定约束的含义

标签 c++ cplex gurobi

我正在围绕 Gurobi 和 Cplex 编写一个小型包装器,以便我编写的模型独立于求解器。我对 Gurobi 非常熟悉,但对 CPLEX 还很陌生,并且在复制我经常使用的某些 API 调用时遇到了困难。

具体来说,我无法弄清楚如何将感知传递给 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
}

我无法弄清楚如何传递目标中变量的系数。我希望能够在创建变量时(或至少在创建变量后立即)执行此操作,以便我可以拥有与 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
  }

最佳答案

为了您的addConstr方法你将不得不使用 switch 语句(不幸的是,正如你希望避免的那样)。通过 CPLEX C++ API,可以使用重载的 <= 构建约束。 , == ,和>=运算符或使用 IloRange 之一构造函数。例如:

   IloRange constraint;
   switch (sense) {
   case 'L':
      constraint = (expr <= rhs);
      // Equivalent to:
      // constraint = IloRange(env, 0.0, expr, rhs);
      break;
   case 'G':
      constraint = (expr >= rhs);
      // Equivalent to:
      // constraint = IloRange(env, rhs, expr, IloInfinity);
      break;
   case 'E':
      constraint = (expr == rhs);
      // Equivalent to:
      // constraint = IloRange(env, rhs, expr, rhs);
      break;
   default:
      // This should not happen.
      abort();
   }
   _cplex_model.add(constraint);

我对 Gurobi API 不太熟悉,但是对于您的 addVar看起来您需要重构它来调用 GRBModel::setObjective() 方法单独(创建变量后)。使用 CPLEX C++ API,您可以以类似的方式单独创建目标。例如,使用 IloMinimize ,像这样:

model.add(IloMinimize(env, objexpr));

注意:CPLEX C API(又名可调用库)可能更符合您的原始代码的精神。也就是说,您可以使用 char 设置约束的意义。参数,您可以在创建变量时设置变量的目标值。您可能需要承担更多工作,但您可以考虑围绕 CPLEX C API 创建一个自定义的轻量级面向对象包装器以满足您的需求。

关于c++ - 在 CPLEX 中指定约束的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58107655/

相关文章:

c++ - 如何在 dlib 正面面部检测器中拆分级联级别?

excel - 如何将 CPLEX 解决方案写入 excel

mathematical-optimization - 尽管数学上不可能,但 Gurobi 报告了无限模型

c++ - 如何在 AST 中使用 Boost Spirit 自动规则?

c++ - 内存区域和内存分配器有什么区别?

python - 如何使用 python 安装 CPLEX?

c++ - 编译Gurobi示例代码时出现链接器错误

java - Java 中 Gurobi 优化器的 UnsatisfiedLinkError

c# - 从包含 '\0' 个字符的非托管 C++ DLL 返回 LPTSTR

matlab - 是什么原因导致错误 "Row ' c140 8' infeasible, all entries at implied bounds."?我怎样才能在matlab中显示它?