You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用cplexAPI求解二次规划及带二次约束的线性规划

R环境下cplexAPI求解二次规划/二次约束规划实现方案

一、二次规划(QP)实现步骤

二次规划是目标函数含二次项、约束均为线性的优化问题,基于cplexAPI的实现流程如下:

  • 导入cplexAPI包,初始化CPLEX环境指针,创建空的问题实例
  • 配置问题属性:设置优化方向(最小/最大化),添加决策变量的线性目标系数、上下界、变量类型
  • 调用setQC函数传入目标函数的二次项系数矩阵(CPLEX要求二次矩阵为半正定/半负定,对应最小化/最大化场景,默认使用上三角矩阵存储减少冗余)
  • 调用addRows添加所有线性约束,逻辑与线性规划完全一致
  • 调用solveCplex求解,通过getObjVal、getX等函数提取求解结果
  • 求解完成后关闭问题实例、释放CPLEX环境,避免内存泄漏

QP代码示例

以下示例为最小化x1² + x2² + x3²,约束x1+x2+x3=1,x1,x2,x3≥0:

library(cplexAPI)
# 初始化环境与问题
env <- openEnv()
prob <- createProb(env, "qp_example")
# 设置为最小化问题
setObjDir(env, prob, CPX_MIN)
# 定义3个连续变量,下界0,上界Inf,线性目标系数都是0(目标全为二次项)
nvar <- 3
lb <- rep(0, nvar)
ub <- rep(CPX_INFBOUND, nvar)
obj_lin <- rep(0, nvar)
vtype <- rep(CPX_CONTINUOUS, nvar)
addCols(env, prob, nvar, obj_lin, lb, ub, vtype, rep("", nvar))
# 设置目标二次项:CPLEX二次目标格式为0.5*x^T Q x,因此要得到x_i²系数为1,Q矩阵对角线元素设为2
Qmat <- Matrix::Diagonal(nvar, 2)
# 传入二次矩阵
setQC(env, prob, Qmat@p, Qmat@i, Qmat@x)
# 添加线性约束:x1+x2+x3 = 1
ncon <- 1
rhs <- c(1)
sense <- c("E")
beg <- c(0)
ind <- c(0,1,2)
val <- c(1,1,1)
addRows(env, prob, ncon, rhs, sense, beg, ind, val, rep("", ncon))
# 求解
solveCplex(env, prob)
# 提取结果
obj_val <- getObjVal(env, prob)
x_sol <- getX(env, prob, 0, nvar-1)
print(paste0("最优目标值:", round(obj_val,4)))
print(paste0("最优解:x1=", round(x_sol[1],4), ", x2=", round(x_sol[2],4), ", x3=", round(x_sol[3],4)))
# 释放资源
freeProb(env, prob)
closeEnv(env)

二、带二次约束的线性规划(QCQP)实现步骤

这类问题目标函数为线性,约束中存在二次项,实现流程和QP基本一致,区别是不需要设置目标二次项,改为通过addQConstr函数添加二次约束:

  • 初始化CPLEX环境和问题实例,配置决策变量的线性目标系数、上下界、变量类型
  • 先添加所有线性约束,逻辑和线性规划一致
  • 调用addQConstr函数逐条添加二次约束,传入二次项的行索引、列索引、系数,以及约束的一次项系数、右端项、约束方向
  • 求解后提取结果,释放资源

QCQP代码示例

以下示例为最小化x1+x2+x3,约束x1² + 2x2² ≤ 1、x1+x2+x3 ≥ 0.5,所有变量≥0:

library(cplexAPI)
# 初始化环境与问题
env <- openEnv()
prob <- createProb(env, "qcqp_example")
setObjDir(env, prob, CPX_MIN)
# 定义3个连续变量,线性目标系数都是1,下界0
nvar <- 3
obj_lin <- c(1,1,1)
lb <- rep(0, nvar)
ub <- rep(CPX_INFBOUND, nvar)
vtype <- rep(CPX_CONTINUOUS, nvar)
addCols(env, prob, nvar, obj_lin, lb, ub, vtype, rep("", nvar))
# 添加线性约束:x1+x2+x3 ≥ 0.5
ncon_lin <- 1
rhs_lin <- c(0.5)
sense_lin <- c("G")
beg <- c(0)
ind <- c(0,1,2)
val <- c(1,1,1)
addRows(env, prob, ncon_lin, rhs_lin, sense_lin, beg, ind, val, rep("", ncon_lin))
# 添加二次约束:x1² + 2x2² ≤ 1,对应0.5*x^T Q x ≤ 1,因此Q矩阵(0,0)=2、(1,1)=4
qrow <- c(0,1)
qcol <- c(0,1)
qval <- c(2,4)
# 该二次约束无一次项,线性部分留空
lin_ind <- integer(0)
lin_val <- numeric(0)
addQConstr(env, prob, length(lin_ind), length(qval), 1, "L", lin_ind, lin_val, qrow, qcol, qval, "quad_constr1")
# 求解
solveCplex(env, prob)
# 提取结果
obj_val <- getObjVal(env, prob)
x_sol <- getX(env, prob, 0, nvar-1)
print(paste0("最优目标值:", round(obj_val,4)))
print(paste0("最优解:x1=", round(x_sol[1],4), ", x2=", round(x_sol[2],4), ", x3=", round(x_sol[3],4)))
# 释放资源
freeProb(env, prob)
closeEnv(env)

注意事项

  • 所有涉及索引的参数均从0开始计数,和CPLEX的C API逻辑保持一致,不要使用R默认的1索引,否则会出现报错或计算错误
  • 二次项存储默认使用上三角矩阵,不要重复传入下三角的对称元素,避免系数计算翻倍
  • 求解前可以调用setIntParm(env, prob, CPX_PARAM_SCRIND, 1)打开求解日志输出,方便排查求解过程中的问题
  • 若遇到非凸二次规划/二次约束问题,需要开启CPLEX的非凸求解参数:setIntParm(env, prob, CPX_PARAM_SOLUTIONTARGET, CPX_SOLUTIONTARGET_FIRSTORDER),否则会报错提示问题非凸

内容的提问来源于stack exchange,提问作者wayne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:06:00