基于R语言的带约束糖果权重分配函数适配方案问询
糖果权重分配的R语言实现与场景适配
初始需求与现有实现
给11个糖果(candy_1至candy_11)分配权重,需满足以下约束:
- 所有权重和为1
- 单个权重取值范围为0至1
- candy_6权重最高且为0.5
- candy_6 > candy_7 > candy_8 > candy_9 > candy_10 > candy_11
- candy_6 > candy_5 > candy_4 > candy_3 > candy_2 > candy_1
- candy_7 = candy_5,candy_8 = candy_4,candy_9 = candy_3,candy_10 = candy_2,candy_11 = candy_1
注:本质是生成以candy_6为中心的对称离散分布权重
现有近似实现函数:
generate_sequence <- function(n, pos, max_val) { other_val <- (1 - max_val) / (n - 1) seq <- rep(other_val, n) seq[pos] <- max_val for (i in 1:n) { distance <- abs(i - pos) seq[i] <- seq[i] - distance * other_val / (n / 2) } return(seq) } # 输出结果 print(data.frame(candy_number = seq(1:11), weights = generate_sequence(11, 6, 0.5)))
输出结果:
candy_number weights 1 1 0.004545455 2 2 0.013636364 3 3 0.022727273 4 4 0.031818182 5 5 0.040909091 6 6 0.500000000 7 7 0.040909091 8 8 0.031818182 9 9 0.022727273 10 10 0.013636364 11 11 0.004545455
可选可视化代码:
library(ggplot2) df <- data.frame(candy_number = seq(1:11), weights = generate_sequence(11, 6, 0.5)) ggplot(df, aes(x = factor(candy_number), y = weights)) + geom_bar(stat = "identity", fill = "steelblue") + theme_minimal() + labs(x = "Candy Number", y = "Weights", title = "Candy Weights Distribution") + theme(axis.text.x = element_text(angle = 90, hjust = 1))
场景1:指定candy_1和candy_11的固定权重值
新增参数接收边缘固定值,同时保证对称、单调递减及权重和为1的约束。修改后的函数如下:
generate_fixed_edge_weights <- function(n, pos, max_val, fixed_edge_val) { # 输入合法性校验 if (fixed_edge_val <= 0 || max_val + 2*fixed_edge_val >= 1) { stop("固定边缘值需大于0,且max_val + 2*fixed_edge_val必须小于1") } # 计算剩余可分配权重与中间节点数量 remaining_weight <- 1 - max_val - 2*fixed_edge_val mid_nodes <- n - 3 # 初始化序列 seq <- rep(0, n) seq[pos] <- max_val seq[1] <- fixed_edge_val seq[n] <- fixed_edge_val # 分配中间节点权重,保证对称且单调递增至峰值 steps <- pos - 1 interval_weight <- remaining_weight / ((steps-1)*2) for (i in 2:(pos-1)) { distance_from_edge <- i - 1 seq[i] <- fixed_edge_val + interval_weight * distance_from_edge seq[n - i + 1] <- seq[i] } # 校准权重和(处理浮点误差) if (abs(sum(seq) - 1) > 1e-6) { warning("权重和存在微小误差,已自动校准") seq <- seq / sum(seq) } return(seq) } # 示例调用:指定candy1和candy11权重为0.01,candy6权重为0.5 weights_scene1 <- generate_fixed_edge_weights(11, 6, 0.5, 0.01) print(data.frame(candy_number = 1:11, weights = weights_scene1))
场景2:以candy_9为权重峰值,左右两侧单调递减
峰值位置改为9,左侧candy1到candy8权重单调递减(越靠近9权重越高),右侧candy10、candy11权重单调递减(越远离9权重越低)。修改后的函数如下:
generate_peak_at9_weights <- function(n, max_val) { peak_pos <- 9 # 输入合法性校验 if (max_val >= 1) { stop("峰值权重必须小于1") } remaining_weight <- 1 - max_val left_nodes <- 8 # candy1至candy8 right_nodes <- 2 # candy10至candy11 # 初始化序列 seq <- rep(0, n) seq[peak_pos] <- max_val # 分配左侧权重:线性递增至峰值(实现1-8单调递减) left_total_weight <- remaining_weight * (left_nodes / (left_nodes + right_nodes)) left_step <- left_total_weight / sum(1:left_nodes) for (i in 1:left_nodes) { seq[i] <- left_step * i } # 分配右侧权重:线性递减 right_total_weight <- remaining_weight * (right_nodes / (left_nodes + right_nodes)) right_step <- right_total_weight / sum(1:right_nodes) seq[peak_pos + 1] <- right_step * 2 seq[peak_pos + 2] <- right_step * 1 # 校准权重和 if (abs(sum(seq) - 1) > 1e-6) { seq <- seq / sum(seq) } # 验证单调约束 if (!all(seq[1:left_nodes] == sort(seq[1:left_nodes], decreasing = TRUE)) || !all(seq[peak_pos:n] == sort(seq[peak_pos:n], decreasing = TRUE))) { warning("生成的序列未满足单调递减约束,请检查参数") } return(seq) } # 示例调用:candy9权重为0.4 weights_scene2 <- generate_peak_at9_weights(11, 0.4) print(data.frame(candy_number = 1:11, weights = weights_scene2))
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

