如何用clarabel在R中求解二次约束线性规划

gzszwxb4  于 2023-10-13  发布在  其他
关注(0)|答案(1)|浏览(145)

我正在寻找一些帮助转换成clarabel优化包(二阶锥规划求解器)所需的形式二次约束。
首先,这只是问题的线性部分:

library(clarabel)
library(Matrix)

a = c(1.425, 0.27, -0.085, -0.733, -0.534, 1.402, -0.199, -0.875, -1.586, -2.126)
xl = rep(0, 10)
xu = rep(1, 10)
A = rbind(rep(1, 10), Diagonal(10), -Diagonal(10))
b = c(1, xu, -xl)

x = clarabel(A, b, -a, cones=list(z=1, l=20))$x

这里是二次约束的测试数据:

y = c(0.242, 0.058, 0.204, 0.112, 0.123, 0.143, 0, 0.065, 0, 0.053)
Q = structure(c(1.291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.018, 0.525, 0,
                0, 0, 0, 0, 0, 0, 0, 0.034, 0.02, 0.543, 0, 0, 0, 0, 0, 0, 0,
                0.012, 0.011, 0.015, 0.536, 0, 0, 0, 0, 0, 0, 0.039, 0.021, 0.036,
                0.012, 0.874, 0, 0, 0, 0, 0, 0.064, 0.02, 0.046, 0.009, 0.054,
                0.735, 0, 0, 0, 0, 0.02, 0.007, 0.019, 0.001, 0.025, 0.035, 1.791,
                0, 0, 0, 0.031, 0.018, 0.029, 0.011, 0.032, 0.043, 0.03, 1.242,
                0, 0, 0.008, 0.008, 0.012, 0.045, 0.006, 0.004, 0.008, 0.007,
                0.55, 0, 0.005, 0.007, 0.009, 0.041, 0.003, 0, 0.01, 0.006, 0.062,
                0.479), .Dim = c(10L, 10L))
Q = as(as(Q + lower.tri(Q) * t(Q), 'CsparseMatrix'), 'symmetricMatrix')

我试图施加的二次约束是sqrt((x-y) %*% Q %*% (x-y)) <= 0.1,它等价于x %*% Q %*% x - 2 * x %*% Q %*% y - (0.1^2 - y %*% Q %*% y) <= 0
通过在目标中加入二次项,我做了一个简单的搜索来找到近似解,以了解预期结果:

lambda = 13.8703
x = clarabel(A, b, -a + lambda * -2 * drop(Q %*% y), 2 * lambda * Q, cones=list(z=1, l=20))$x

到目前为止一切都很好,但是我尝试遵循各种将QCQP转换为SOCP的指南(例如herehere),要么产生不可行的错误,要么似乎完全忽略了约束。
这是我尝试过的(两者都不可行):

S = chol(Q)
lin = drop(-2 * Q %*% y)
rhs = drop(0.1^2 - y %*% Q %*% y)
bb = -drop(solve(S, lin))
gamma = -sqrt(drop(crossprod(bb)) + rhs)

res = clarabel(rbind(A, 0, S), c(b, rhs, lin), -a, cones=list(z=1, l=20, q=11))
solver_status_descriptions()[res$status]

res = clarabel(rbind(A, 0, S), c(b, gamma, bb), -a, cones=list(z=1, l=20, q=11))
solver_status_descriptions()[res$status]

如果你能帮忙的话,我将不胜感激。谢谢你,谢谢

nfg76nw0

nfg76nw01#

事实证明,我上面的原始尝试既不正确,因为它如何将锥参数传递给clarabel,也不正确,因为它需要对称矩阵平方根(根据许多QCQP到SOCP的转换)。下面的例子实际上成功地执行了二次约束:

S = as(expm::sqrtm(Q), 'sparseMatrix')
lin = -2 * drop(Q %*% y)
bb = 0.5*drop(solve(S, -lin))
target = 0.1^2 - drop(y %*% Q %*% y)
x = clarabel(rbind(A, -0.1, S), c(b, 0, bb), -a, cones=list(z=1, l=20, q=11))$x
sqrt((x - y) %*% Q %*% (x - y)) # => 0.1

不幸的是,在我的真实的问题中,我有一个非常大的稀疏矩阵,所以我在寻找一个只使用乔莱斯基分解的变换。由于线性项,使用上述方法不起作用,但可以通过为线性项添加具有等式约束的额外变量来避免(注意A矩阵和零锥大小的变化):

S = chol(Q)
A2 = rbind(cbind(Diagonal(10), -Diagonal(10)), cbind(A, Matrix(0, nrow(A), 10)))
b2 = c(y, b)
a2 = c(a, rep(0, 10))
x = clarabel(rbind(A2, c(rep(-0.1, 20)), cbind(Matrix(0, 10, 10), S)), c(b2, rep(0, 11)), -a2, cones=list(z=11, l=20, q=11))$x[1:10]
sqrt((x - y) %*% Q %*% (x - y)) # => 0.1

这也有点不令人满意,因为从性能的Angular 来看,我的问题中的变量(和约束)数量增加一倍似乎是不可取的。最后,我在第9页找到了一个可以使用Cholesky分解的转换here

S = chol(Q)
lin = -2 * drop(Q %*% y)
target = 0.1^2 - drop(y %*% Q %*% y)
x = clarabel(rbind(A, lin/2, S, -lin/2), c(b, (1+target)/2, rep(0, 10), (1-target)/2), -a, cones=list(z=1, l=20, q=12))$x
sqrt((x - y) %*% Q %*% (x - y)) # => 0.1

相关问题