CVXR 中 DCP 规则的问题
Problems with DCP rules in CVXR
我正在使用 CVXR
建模包来解决凸优化问题。我确定问题是凸的并且它遵循 DCP 规则,但是如果我使用 CVXR
检查 DCP 规则它 returns False
。但是,如果我采取完全相同的问题并使用 CVXPY
检查它 returns True
(如预期的那样)
这里发生了什么?我在 R 和 Python:
中附加了此行为的最小可重现示例
R 代码使用 CVXR
library(splines2)
library(CVXR)
deriv_basis = splines2::dbs(seq(0, 1, length.out=100), degree=3, intercept=T, df=30, derivs=2)
R = t(deriv_basis) %*% deriv_basis
beta_var = CVXR::::Variable(nrow(R))
q = CVXR::quad_form(beta_var, R)
CVXR::is_dcp(q)
[1] FALSE
write.table(x=R, file='R.csv'), row.names=F, sep=';')
Python 代码使用 CVXPY
import cvxpy
import pandas as pd
R = pd.read_csv('R.csv', sep=';').values
beta_var = cvxpy.Variable(R.shape[1])
q = cvxpy.quad_form(beta_var, R)
q.is_dcp()
Out[1]: True
有人可以解释这里发生了什么以及如何解决它以便我可以使用 CVXR 吗?
问题是 R 矩阵中的负特征值。如果你通过将它设置为零来修复它,那么它就满足 dcp 条件。我还修复了问题代码中的语法错误并删除了多余的 :: 。另一种可能性(未显示)是使用 pracma 包中的 nearest_spd
来调整 R 矩阵。
library(splines2)
library(CVXR)
deriv_basis <- dbs(seq(0, 1, length.out=100), degree = 3,
intercept = TRUE, df = 30, derivs = 2)
R <- t(deriv_basis) %*% deriv_basis
e <- eigen(R)
# check decomposition
all.equal(R, e$vectors %*% diag(e$values) %*% t(e$vectors),
check.attributes = FALSE)
## [1] TRUE
e$values # note negative value
## [1] 1.095213e+08 1.095213e+08 1.056490e+07 1.055430e+07 1.052481e+07
## [6] 1.046063e+07 1.034247e+07 1.015017e+07 9.866358e+06 9.485145e+06
## [11] 8.643220e+06 8.280963e+06 7.549803e+06 6.731472e+06 5.853402e+06
## [16] 4.949804e+06 4.056714e+06 3.209045e+06 2.437320e+06 1.759963e+06
## [21] 1.214976e+06 7.785251e+05 4.590441e+05 2.428199e+05 1.107300e+05
## [26] 4.060476e+04 1.040537e+04 1.320942e+03 7.239578e-09 -5.019224e-09
# zap negative eigenvalues making them zero
R <- with(e, vectors %*% diag(pmax(values, 0)) %*% t(vectors))
beta_var <- Variable(nrow(R))
q <- quad_form(beta_var, R)
is_dcp(q)
## [1] TRUE
cvxpy
应该给出与 G. Grothendieck 暗示的 CVXR
相同的结果,因为 DCP 规则是相同的。 cvxpy
的最新版本似乎出现了问题。我在 cvxpy github.
上开了一个问题
我正在使用 CVXR
建模包来解决凸优化问题。我确定问题是凸的并且它遵循 DCP 规则,但是如果我使用 CVXR
检查 DCP 规则它 returns False
。但是,如果我采取完全相同的问题并使用 CVXPY
检查它 returns True
(如预期的那样)
这里发生了什么?我在 R 和 Python:
中附加了此行为的最小可重现示例R 代码使用 CVXR
library(splines2)
library(CVXR)
deriv_basis = splines2::dbs(seq(0, 1, length.out=100), degree=3, intercept=T, df=30, derivs=2)
R = t(deriv_basis) %*% deriv_basis
beta_var = CVXR::::Variable(nrow(R))
q = CVXR::quad_form(beta_var, R)
CVXR::is_dcp(q)
[1] FALSE
write.table(x=R, file='R.csv'), row.names=F, sep=';')
Python 代码使用 CVXPY
import cvxpy
import pandas as pd
R = pd.read_csv('R.csv', sep=';').values
beta_var = cvxpy.Variable(R.shape[1])
q = cvxpy.quad_form(beta_var, R)
q.is_dcp()
Out[1]: True
有人可以解释这里发生了什么以及如何解决它以便我可以使用 CVXR 吗?
问题是 R 矩阵中的负特征值。如果你通过将它设置为零来修复它,那么它就满足 dcp 条件。我还修复了问题代码中的语法错误并删除了多余的 :: 。另一种可能性(未显示)是使用 pracma 包中的 nearest_spd
来调整 R 矩阵。
library(splines2)
library(CVXR)
deriv_basis <- dbs(seq(0, 1, length.out=100), degree = 3,
intercept = TRUE, df = 30, derivs = 2)
R <- t(deriv_basis) %*% deriv_basis
e <- eigen(R)
# check decomposition
all.equal(R, e$vectors %*% diag(e$values) %*% t(e$vectors),
check.attributes = FALSE)
## [1] TRUE
e$values # note negative value
## [1] 1.095213e+08 1.095213e+08 1.056490e+07 1.055430e+07 1.052481e+07
## [6] 1.046063e+07 1.034247e+07 1.015017e+07 9.866358e+06 9.485145e+06
## [11] 8.643220e+06 8.280963e+06 7.549803e+06 6.731472e+06 5.853402e+06
## [16] 4.949804e+06 4.056714e+06 3.209045e+06 2.437320e+06 1.759963e+06
## [21] 1.214976e+06 7.785251e+05 4.590441e+05 2.428199e+05 1.107300e+05
## [26] 4.060476e+04 1.040537e+04 1.320942e+03 7.239578e-09 -5.019224e-09
# zap negative eigenvalues making them zero
R <- with(e, vectors %*% diag(pmax(values, 0)) %*% t(vectors))
beta_var <- Variable(nrow(R))
q <- quad_form(beta_var, R)
is_dcp(q)
## [1] TRUE
cvxpy
应该给出与 G. Grothendieck 暗示的 CVXR
相同的结果,因为 DCP 规则是相同的。 cvxpy
的最新版本似乎出现了问题。我在 cvxpy github.