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

如何用CVXR获取优化问题的多个解?现有代码结果重复求助

问题:生成满足约束的多组不同解

约束条件

需要找到多组满足以下条件的变量组合(TXs[1], TXs[2], TXs[3], TXs[4], TXs[5], TZs):

# 变量定义
TXs <- Variable(5)
TZs <- Variable(1)

# 目标:总和尽可能接近100
obj = abs(TXs[1] + TXs[2] + TXs[3] + TXs[4] + TXs[5] + TZs - 100)

# 约束条件
# 1. 变量取值范围
abs(TXs[1] - 2) <=1
abs(TXs[2] - 55) <= 2
abs(TXs[3] - 25) <= 0.5
abs(TXs[4] - 8) <= 1
abs(TXs[5] - 7) <= 1
abs(TZs[1] - 1.5) <= 1

# 2. 相关系数约束
cor(TXs[1], TXs[2]) = 0.77
cor(TXs[3], TXs[2]) = 0.85
cor(TXs[4], TXs[2]) = 0.88
cor(TXs[5], TXs[2]) = 0.99
cor(TZs, TXs[2]) = 0.4

# 3. 总和接近100
abs(TXs[1] + TXs[2] + TXs[3] + TXs[4] + TXs[5] + TZs[1] - 100) <= 0.001

现有代码问题

你编写的CVXR代码每次运行都得到相同结果,核心原因是:

  • 代码中将相关系数约束转化为严格等式(比如((TXs[1]-2)/1) == 0.77*(TXs[2]-55)/2),这使得所有变量都被TXs[2]线性表示;
  • 加上总和约束后,整个系统是唯一解的线性方程组,因此循环多次也只会得到同一个结果。

解决方案

方法一:修改CVXR代码,引入松弛与随机化目标

通过放松约束范围、加入随机化目标函数,让解空间从单点扩展为区域,从而生成多个不同解:

library(CVXR)

k <- 10
solutions <- matrix(NA, nrow = k, ncol = 6)

set.seed(123) # 可选,保证结果可复现

for (i in 1:k) {
  # 每次循环重新定义变量,避免CVXR缓存影响
  TXs <- Variable(5)
  TZs <- Variable(1)
  sum_vars <- sum(TXs) + TZs
  
  # 加入随机化小扰动目标,引导优化到不同可行点
  rand_weights <- rnorm(6, 0, 0.01) # 小权重,不影响核心目标
  obj <- abs(sum_vars - 100) + t(rand_weights) %*% c(TXs, TZs)
  
  # 放松相关系数约束为区间(允许微小波动)
  prob <- Problem(Minimize(obj),
                  list(
                    # 变量范围约束
                    abs(TXs[1] - 2) <= 1,
                    abs(TXs[2] - 55) <= 2,
                    abs(TXs[3] - 25) <= 0.5,
                    abs(TXs[4] - 8) <= 1,
                    abs(TXs[5] - 7) <= 1,
                    abs(TZs[1] - 1.5) <= 1,
                    # 放松相关系数约束为±0.01的区间
                    abs( ((TXs[1]-2)/1) - 0.77*((TXs[2]-55)/2) ) <= 0.01,
                    abs( ((TXs[3]-25)/0.5) - 0.85*((TXs[2]-55)/2) ) <= 0.01,
                    abs( ((TXs[4]-8)/1) - 0.88*((TXs[2]-55)/2) ) <= 0.01,
                    abs( ((TXs[5]-7)/1) - 0.99*((TXs[2]-55)/2) ) <= 0.01,
                    abs( ((TZs-1.5)/1) - 0.4*((TXs[2]-55)/2) ) <= 0.01,
                    # 总和约束保留
                    abs(sum_vars - 100) <= 0.001
                  ))
  
  result <- solve(prob)
  solutions[i,] <- c(result$getValue(TXs), result$getValue(TZs))
}

solutions <- as.data.frame(solutions)
colnames(solutions) <- c("TXs[1]","TXs[2]","TXs[3]","TXs[4]","TXs[5]","TZs")
solutions$Somme <- rowSums(solutions)
print(solutions)

方法二:蒙特卡洛采样+约束验证(无需CVXR)

直接在变量范围内生成随机样本,筛选满足约束的解:

k <- 10
solutions <- data.frame(matrix(NA, nrow = k, ncol = 6))
colnames(solutions) <- c("TXs[1]","TXs[2]","TXs[3]","TXs[4]","TXs[5]","TZs")

# 自定义clamp函数,将值限制在指定范围内
clamp <- function(x, min_val, max_val) {
  return(pmax(min_val, pmin(max_val, x)))
}

set.seed(123)
count <- 0

while(count < k) {
  # 1. 随机生成核心变量TXs[2]
  tx2 <- runif(1, 55-2, 55+2)
  
  # 2. 根据相关系数计算基准值,加入小扰动并限制范围
  tx1 <- clamp(2 + 0.77*(tx2-55)*0.5 + rnorm(1, 0, 0.05), 1, 3)
  tx3 <- clamp(25 + 0.85*(tx2-55)*0.25 + rnorm(1, 0, 0.02), 24.5, 25.5)
  tx4 <- clamp(8 + 0.88*(tx2-55)*0.5 + rnorm(1, 0, 0.05), 7, 9)
  tx5 <- clamp(7 + 0.99*(tx2-55)*0.5 + rnorm(1, 0, 0.05), 6, 8)
  tz <- clamp(1.5 + 0.4*(tx2-55)*0.5 + rnorm(1, 0, 0.05), 0.5, 2.5)
  
  # 3. 验证总和是否符合要求
  total <- tx1 + tx2 + tx3 + tx4 + tx5 + tz
  if(abs(total - 100) <= 0.001) {
    count <- count +1
    solutions[count,] <- c(tx1, tx2, tx3, tx4, tx5, tz)
  }
}

solutions$Somme <- rowSums(solutions)
print(solutions)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:58