c++ API概述


c++ API概述

本节介绍了GuRoCI C++接口。本手册首先简要介绍接口中公开的类以及这些类上最重要的方法。然后,它继续以所有可用类和方法的全面表示

如果您是Gurobi Optimizer的新手,我们建议您从快速入门指南或者是例子之旅.这些文档提供了如何使用此处描述的类和方法的具体示例。

环境

使用Gurobi c++接口的第一步是创建一个环境对象。环境使用GRBEnv类。环境充当与一组优化运行相关联的所有数据的容器。程序中通常只需要一个环境对象。

模型

您可以在一个环境中创建一个或多个优化模型。每个模型都表示为类的一个对象GRBModel.模型由一组决策变量(类对象组成GRBVar),对这些变量的线性或二次目标函数(用GRBModel::setObjective),以及对这些变量(类的对象)的一组约束Grbconstr.GRBQConstrGrbsos.GRBGenConstr). 每个变量都有一个相关的下限、上限和类型(连续、二进制等)。每个线性或二次约束都有关联的意义(小于或等于、大于或等于或等于)和右侧值。提到这个部分有关变量和约束的更多信息。

当在模型中添加变量时,也可以定义线性目标(参见GRBModel: addVar)然而GRBModel::setObjective通常更可取,因为它更容易阅读和维护。

线性约束通过构建线性表达式(类的对象)来指定GRBLinExpr),然后指定这些表达式之间的关系(例如,要求一个表达式等于另一个表达式)。二次约束以类似的方式构建,但使用二次表达式(类的对象)GRBQuadExpr)相反。

通过从文件加载模型(使用适当的GRBModel构造函数)或逐步构建,首先构建类的空对象GRBModel然后随后呼唤GRBModel: addVarGRBModel: addVars添加其他变量,和GRBModel: addConstrGRBModel::addQConstrGRBModel::addSOS,或任何一个GRBModel: addGenConstrXxx方法来添加约束。模型是动态的实体;您总是可以添加或删除变量或约束。

我们经常提到班级一个优化模型。具有线性目标函数、线性约束和连续变量的模型为线性规划(LP).如果目标是二次的,模型是a二次规划(QP). 如果任何约束为二次约束,则模型为Quadratically-Constrained计划(QCP).我们有时也会讨论QCP的特殊情况二阶锥程序(SOCP). 如果模型包含任何整数变量、半连续变量、半整数变量、特殊有序集(SOS)约束或一般约束,则模型为混合整数程序(MIP).我们还将有时讨论特殊情况的MIP,包括混合整数线性程序(MILP)混合整数二次程序(MIQP)混合整数二次约束规划,混合整数二阶锥规划(MISOCP). Gurobi优化器处理所有这些模型类。

解决模型

一旦建立了模型,就可以调用grbmodel ::优化计算一个解。默认情况下,优化将使用它并发优化器用barrier算法求解QP和QCP模型,用branch-and-cut算法求解混合整数模型。解决方案存储在一组属性的模型。属性上的一组属性查询方法可以查询这些属性GRBModelGRBVarGrbconstr.GRBQConstrGrbsos.,GRBGenConstr类。

Gurobi算法会仔细跟踪模型的状态,因此调用grbmodel ::优化只在自上次优化模型以来相关数据发生更改时执行进一步优化。如果您想放弃以前计算的解决方案信息,并在不更改模型的情况下从头开始优化,您可以调用GRBModel:重置

解决MIP模型后,可以调用grbmodel :: fixedmodel.计算相关的固定的模型此模型与输入模型相同,只是所有整数变量在MIP解决方案中都固定为其值。在某些应用中,计算MIP模型的连续版本的信息(例如,双变量、灵敏度信息等)非常有用。

多种解决方案和多目标

默认情况下,Gurobi优化器假定您的目标是为具有单个目标函数的模型找到一个经验证的最优解决方案。Gurobi提供的特性允许您放松这些假设。您应该参考溶液池有关如何请求多个解决方案的信息,或有关多目标有关如何指定多个目标函数并控制它们之间的权衡的信息。

不可行的模型

如果发现模型不可行,您有几个选项。您可以尝试诊断不可行性的原因,尝试修复不可行性,或者两者兼而有之。要获取对诊断不可行原因有用的信息,请调用grbmodel :: computeiis.计算不可约不一致子系统(IIS)。这种方法可以用于连续模型和MIP模型,但是您应该知道MIP版本可能非常昂贵。此方法填充一组IIS属性。

试图修复不可行,呼叫GRBModel::feasRelax计算模型的可行性松弛。这种松弛允许您找到一个解,使违反约束的幅度最小化。

查询和修改属性

与Gurobi模型相关的大多数信息存储在一组属性中。某些属性与模型的变量相关联,其中一些具有模型的约束,以及一些与模型本身的一个属性。要提供一个简单的例子,解决优化模型原因导致X要填充的变量属性。属性,例如X用户不能直接修改由Gurobi优化器计算的变量,而其他变量,如变量下界属性)可以。

查询属性使用grbvar :: get.GRBConstr::GRBQConstr::getGRBSOS :: GET.GRBGenConstr::grbmodel :: get.,修改使用GRBVar:集grbconstr :: set.GRBQConstr:集grbgenconstr :: set.GRBModel::set.按类型将属性分组为一组枚举(grb_charattr.双重属性GRB_IntAttrGRB_StringAttr). 这个get ()集合()方法是重载的,因此属性的类型决定返回值的类型。因此,constr.get (GRB.DoubleAttr.RHS)返回一个double, whileconstr.get (GRB.CharAttr.Sense)返回一个字符。

如果您希望检索一组变量或约束的属性值,通常更有效的方法是使用关联的数组方法GRBModel对象。方法grbmodel :: get.包括允许查询或修改变量数组或约束的属性值的签名。

属性的完整列表可以在属性部分。

附加的模型修改信息

对现有模型的大多数修改都是通过属性接口完成的(例如,对变量边界、约束右边等的更改)。主要的例外是对约束矩阵和目标函数的修改。

可以通过几种方式修改约束矩阵。第一个是打电话给chgcoefs方法GRBModel对象更改单个矩阵系数。此方法可用于修改现有非零的值,将现有非零设置为零,或创建新的非零。当您从模型中移除一个变量或约束时(通过GRBModel:删除方法)。与删除约束或变量相关联的非零值与约束或变量本身一起移除。

模型目标函数也可以通过几种方式进行修改。最简单的方法是构建一个表达式来捕获目标函数(aGRBLinExprGRBQuadExpr对象),然后将该表达式传递给方法GRBModel::setObjective.如果你想修改目标,你可以直接打电话setobjective.再次用一个新的GRBLinExprGRBQuadExpr对象。

对于线性目标函数,另一种方法是setobjective.就是使用obj.用于修改单个线性目标系数的变量属性。

如果变量具有分段线性目标,则可以使用grbmodel :: setpwlobj.方法。每个相关变量调用一次方法一次。Gurobi Simplex求解器包括手机万博登录用于凸分段 - 线性物镜函数的算法支持,因此对于连续型号,您应该看到使用此功能的实质性效益。要清除先前指定的分段线性目标函数,只需设置obj.将对应变量上的属性设置为0。

懒惰的更新

关于Gurobi Optimizer中的模型修改的一个重要项目是它在a中执行懒惰的这意味着修改不会立即影响模特。相反,它们将排队并在稍后应用。如果您的程序只是简单地创建一个模型并解决它,那么您可能永远不会注意到这种行为。但是,如果在应用修改之前询问有关模型的信息,那么延迟更新方法的细节可能与您相关。

正如我们刚才提到的,模型修改(绑定更改、右侧更改、目标更改等)被放置在一个队列中。这些排队修改可以以三种不同的方式应用于模型。第一个是通过显式调用GRBModel::更新. 第二种是打电话给grbmodel ::优化. 第三种是打电话给GRBModel:写写出模型。第一种情况使您可以细粒度控制何时应用修改。第二种和第三种假设您希望在优化模型或将模型写入磁盘之前应用所有挂起的修改。

为什么Gurobi接口以这种方式运行?有几个原因。首先,这种方法使对模型执行多次修改变得更加容易,因为模型在修改之间保持不变。其次,处理模型修改可能会非常昂贵,特别是在Compute Server环境中,其中修改需要在机器之间进行通信。因此,准确地了解何时应用这些修改是很有用的。一般来说,如果您的程序需要对模型进行多次修改,您应该以阶段为目标,即您进行一组修改,然后更新,然后进行更多修改,然后再次更新,等等。在每次修改之后进行更新可能会非常昂贵。

如果您忘记调用update,您的程序不会崩溃。您的查询将简单地返回来自上次更新点的请求数据的值。如果您尝试查询的对象不存在,那么您将得到NOT_IN_MODEL例外。

自早期的Gurobi版本以来,Lazy更新的语义已更改。虽然绝大多数计划不受这种变化的影响,但可以使用UpdateMode参数,以便在遇到问题时恢复到先前的行为。

管理参数

Gurobi优化器提供了一组参数,允许您控制优化过程的许多细节。可行性和最优性容差、算法选择、探索MIP搜索树的策略等因素可以通过在开始优化之前修改Gurobi参数来控制。参数可以是int一串

设置参数的最简单方法是通过GRBModel::set模型对象上的方法。同样,可以查询参数值grbmodel :: get.

还可以在Gurobi环境对象上设置参数,使用GRBEnv:集. 请注意,每个模型在创建时都有自己的环境副本,因此对原始环境的参数更改对现有模型没有影响。

您可以使用文件读取一组参数设置GRBEnv: readParams,或使用GRBEnv: writeParams

我们还包含了一个自动参数调优工具,它探索许多不同的参数更改集,以便找到一组可以提高性能的参数。你可以打电话GRBModel::tune调用模型上的调优工具。指的是参数调整工具章节以获取更多信息。

可以在的gurobi参数列表参数部分。

内存管理

在C++程序中必须始终考虑内存管理。特别是,GuROBI库和用户程序共享相同的C++堆,因此用户必须知道GoRoi库如何使用这个堆的某些方面。使用Gurobi优化器时管理内存的基本规则如下:

  • 与其他动态分配的C ++对象一样,GRBEnvGRBModel对象应该使用关联的析构函数来释放。换句话说,给定aGRBModel目的m,你应该打电话删除我当您不再使用m
  • 与模型相关联的对象(例如,Grbconstr.GRBQConstrGrbsos.GRBGenConstr,GRBVar对象)由模型管理。特别是,删除模型将删除所有关联对象。同样,从模型中删除对象(使用GRBModel:删除)也将删除该对象。
  • 一些Gurobi方法返回一个对象或值数组。例如,GRBModel: addVars返回GRBVar对象。释放返回的数组是用户的责任(使用删除[]). 参考手册指示方法何时返回堆分配的结果。

这些规则的一个结果是,一旦释放,您必须小心不要使用对象。对于环境和型号,这是毫无疑问的,您可以明确调用析构函数,但可能不太清楚,因为约束和变量,当删除相关的模型时被隐式删除。

监控进度 - 日志记录和回调

可以通过Gurobi日志记录来监控优化的进程。默认情况下,Gurobi将输出发送到屏幕上。可以使用一些简单的控件来修改默认的日志记录行为。如果希望将输出直接输出到文件和屏幕,请在GRBEnv构造函数。您可以修改日志文件参数,如果希望在创建环境对象后将日志重定向到其他文件。测井输出的频率可以通过displayinterval.参数,可以完全关闭日志记录OutputFlag范围。可以在GUROBI日志文件中找到的详细描述记录部分。

更详细的进度监控可以通过grbcallback.类。的GRBModel::setCallback方法允许您从Gurobi优化器接收定期回调。你可以通过子类化grbcallback.抽象班,写自己回调()这个类的方法。你可以打电话GRBCallback: getDoubleInfogrbcallback :: getintinfo.GRBCallback: getStringInfoGRBCallback: getSolution从回调中获取有关优化状态的其他信息。

修改求解器行为 - 手机万博登录回调

回调也可用于修改Gurobi Optimizer的行为。最简单的控制回调是GRBCallback:中止,它要求优化器在最方便的时候终止。方法grbcallback :: setsolution.允许您在MIP模型求解期间注入一个可行的解决方案(或部分解决方案)。方法GRBCallback: addCutGRBCallback: addLazy允许您添加切割平面图懒惰的约束分别在MIP优化过程中。方法GRBCallback: stopOneMultiObj允许您中断多目标MIP问题中的一个优化步骤的优化过程,而不停止分层优化过程。

误差处理

Gurobi c++库中的所有方法都可以抛出类型异常GRBException.发生异常时,可以通过检索错误代码来获得有关错误的其他信息(使用方法GRBException: getErrorCode),或通过检索异常消息(使用方法GRBException: getMessage). 可在中找到可能的错误返回代码列表错误代码部分。