在CPLEX中指定约束的意义

时间:2019-09-25 23:13:31

标签: 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
  }

1 个答案:

答案 0 :(得分:3)

对于您的Route::resource('moneyEntries', 'MoneyEntryController'); 方法,您将不得不使用switch语句(不幸的是,您希望避免这种情况)。使用CPLEX C ++ API,可以使用重载的addConstr<===运算符或IloRange构造函数之一来构建约束。例如:

>=

我对Gurobi API不太熟悉,但是对于您的 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); 方法,您似乎希望将其重构为分别调用addVar(在创建变量之后)。使用CPLEX C ++ API,可以以类似的方式分别创建目标。例如,使用IloMinimize,如下所示:

GRBModel::setObjective()

注意:CPLEX C API(又名Callable Library)可能更适合您的原始代码。也就是说,可以使用model.add(IloMinimize(env, objexpr)); 参数设置约束的含义,并且可以在创建变量时设置变量的目标值。您可能需要做更多的工作,但是您可以考虑围绕CPLEX C API创建自定义的轻量级面向对象包装,以适合您的需求。