R语言GA包遗传算法如何指定决策变量等式约束并限制小数位数
针对R GA包约束满足与决策变量小数精度控制的解决方案
1. 控制决策变量为指定位数小数
GA包原生支持实值变量的精度控制,不需要额外改造逻辑:
- 调用
ga()时选择type = "real-valued",直接传入precision参数,参数值设为你需要保留的小数位数即可。比如要保留2位小数,就设置precision = 2,GA生成的所有决策变量都会自动四舍五入到对应位数,不会出现小数位数过多的问题。 - 如果用整数型GA实现,可做简单的变量映射:将需要保留n位小数的变量乘以
10^n转为整数,在整数域做优化,计算适应度时再除以10^n还原为小数即可。
2. 保证约束始终生效的最优方案
不推荐用简单的if判断加惩罚的方式,很容易出现惩罚权重不合理导致约束不生效的问题,推荐用变量降维法天然满足约束:
你的约束是「除0809am时段外,其余时段的percent值之和等于mdp」,假设除0809am之外总共有N个时段,你只需要优化其中N-1个时段的percent值,最后1个非0809am时段的percent值直接用公式last_pct = mdp - sum(其余N-1个非0809am时段的percent)计算即可,这样约束从始至终100%满足,完全不需要加任何惩罚逻辑。
如果需要给最后一个计算得到的percent加上下限约束,只需要给你优化的N-1个变量设置合理的上下限,或者在适应度函数里加简单的边界校验,超出范围就返回极差的适应度值即可。
如果不想用降维法,也可以用自适应惩罚:惩罚值和约束违反的程度挂钩,公式为惩罚值 = abs(sum(非0809am时段percent) - mdp) * 惩罚系数,惩罚系数要比你目标函数的最大可能值高2-3个数量级,保证GA会优先满足约束。
3. 示例代码
library(GA) # 预设参数 mdp <- 0.8 # 给定的约束和值 n_non_0809 <- 7 # 除0809am之外的时段总数 digit_precision <- 2 # 需要保留的小数位数 # 适应度函数:仅优化n_non_0809-1个非0809am时段的percent fitness <- function(x) { # 计算最后一个非0809am时段的percent,天然满足sum等于mdp的约束 last_non_0809_pct <- mdp - sum(x) # 边界校验:保证最后一个percent在合理范围内(可根据你的业务调整上下限) if(last_non_0809_pct < 0 | last_non_0809_pct > 0.3) { return(1e6) # 最小化目标的情况下,超出边界返回极大适应度 } # 拼接所有时段的percent(包含0809am时段,若该时段也为优化变量可同步传入) all_pct <- c(x, last_non_0809_pct, pct_0809am) # 计算x前缀负效用列的总和 total_disutility <- sum(your_dataset[, startsWith(names(your_dataset), "x")] %*% all_pct) return(total_disutility) } # 运行遗传算法 ga_res <- ga( type = "real-valued", fitness = fitness, lower = rep(0, n_non_0809 - 1), # 每个优化变量的下限,可按需调整 upper = rep(0.3, n_non_0809 - 1), # 每个优化变量的上限,可按需调整 precision = digit_precision, # 控制决策变量小数位数 maxiter = 1000, popSize = 50, maximize = FALSE # 目标为最小化总负效用 )
内容的提问来源于stack exchange,提问作者umair durrani
相关产品推荐
相关产品推荐

