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

基于进化算法的图分区问题修正:实现purple节点占优分区

R中进化算法优化图分区的修正方案

问题背景

需要用进化算法对igraph构建的10行5列网格图做分区,要求分成5个诱导子图:

  • 每个子图至少包含5个节点
  • 多数子图中purple节点数量多于orange节点

当前基于GA包实现的代码仅能生成垂直分区方案,无法满足purple占优的要求。

原代码

library(igraph)
library(GA)
library(ggplot2)
library(dplyr)
library(gridExtra)

# original graph
n_rows <- 10
n_cols <- 5
g <- make_lattice(dimvector = c(n_cols, n_rows))
n_nodes <- vcount(g)

node_colors <- rep("white", n_nodes)
for (row in 0:(n_rows-1)) {
    start_index <- row * n_cols + 1
    node_colors[start_index:(start_index+2)] <- "orange"  
    node_colors[(start_index+3):(start_index+4)] <- "purple"    
}

# define fitness function based on constraints
fitness <- function(solution) {
    subgraphs <- split(1:n_nodes, solution)
    
    # check if all subgraphs have at least 5 nodes
    if (any(sapply(subgraphs, length) < 5)) {
        return(-Inf)
    }
    
    # count purple wins
    purple_wins <- sum(sapply(subgraphs, function(sg) {
        sum(node_colors[sg] == "purple") > sum(node_colors[sg] == "orange")
    }))
    
    return(purple_wins)
}

# genetic Algorithm
ga_result <- ga(
    type = "permutation",
    fitness = fitness,
    min = 1,
    max = 5,
    popSize = 50,
    maxiter = 1000,
    run = 100,
    pmutation = 0.2,
    monitor = FALSE,
    keepBest = TRUE
)

# multiple solutions
n_solutions <- 3  # Number of solutions to display
solutions <- ga_result@solution[1:n_solutions,]

for (i in 1:n_solutions) {
    cat("Solution", i, "\n")
    cat("Fitness score:", ga_result@fitness[i], "\n\n")
    plot_subgraphs(solutions[i,], i)
    cat("\n")
}

运行输出

Solution 1 
Fitness score: 2 

Subgraph 1 : 4 9 14 19 24 29 34 39 44 49 
Purple: 10 Orange: 0 

Subgraph 2 : 3 8 13 18 23 28 33 38 43 48 
Purple: 0 Orange: 10 

Subgraph 3 : 2 7 12 17 22 27 32 37 42 47 
Purple: 0 Orange: 10 

Subgraph 4 : 1 6 11 16 21 26 31 36 41 46 
Purple: 0 Orange: 10 

Subgraph 5 : 5 10 15 20 25 30 35 40 45 50 
Purple: 10 Orange: 0 


Solution 2 
Fitness score: 2 

Subgraph 1 : 5 10 15 20 25 30 35 40 45 50 
Purple: 10 Orange: 0 

Subgraph 2 : 2 7 12 17 22 27 32 37 42 47 
Purple: 0 Orange: 10 

Subgraph 3 : 4 9 14 19 24 29 34 39 44 49 
Purple: 10 Orange: 0 

Subgraph 4 : 1 6 11 16 21 26 31 36 41 46 
Purple: 0 Orange: 10 

Subgraph 5 : 3 8 13 18 23 28 33 38 43 48 
Purple: 0 Orange: 10 

核心问题

  1. GA类型选择错误:使用permutation(排列类型)会强制解为节点的排序,天然倾向于垂直/水平的规则分区,限制了解空间的探索
  2. 适应度函数引导性不足:仅统计purple占优的子图数量,没有奖励更优的分区结构(如连通性),也没有强化purple的占优幅度,导致算法困在局部最优的垂直分区中

修正方案

1. 更换GA类型为integer

integer类型允许每个节点独立分配分区编号(1-5),完全匹配图分区的需求,打破排列类型带来的规则分区限制。

2. 优化适应度函数

  • 保留节点数量约束:子图节点数不足5则返回负无穷
  • 增加连通性奖励:给连通的诱导子图额外加分,引导算法生成合理的子图结构
  • 强化purple占优奖励:不仅统计占优子图数量,还根据purple与orange的数量差额外加分,鼓励算法生成purple占比更高的子图

3. 调整GA参数

  • 增大种群规模、迭代次数,提高变异率,帮助算法跳出局部最优
  • 使用适合整数类型的交叉和变异策略

修正后的完整代码

library(igraph)
library(GA)
library(ggplot2)
library(dplyr)
library(gridExtra)

# 构建网格图
n_rows <- 10
n_cols <- 5
g <- make_lattice(dimvector = c(n_cols, n_rows))
n_nodes <- vcount(g)

# 分配节点颜色:每行前3个orange,后2个purple
node_colors <- rep("white", n_nodes)
for (row in 0:(n_rows-1)) {
    start_index <- row * n_cols + 1
    node_colors[start_index:(start_index+2)] <- "orange"  
    node_colors[(start_index+3):(start_index+4)] <- "purple"    
}

# 定义改进的适应度函数
fitness <- function(solution) {
    subgraphs <- split(1:n_nodes, solution)
    
    # 约束:每个子图至少5个节点
    if (any(sapply(subgraphs, length) < 5)) {
        return(-Inf)
    }
    
    # 计算每个子图的核心统计
    subgraph_stats <- lapply(subgraphs, function(sg) {
        list(
            purple = sum(node_colors[sg] == "purple"),
            orange = sum(node_colors[sg] == "orange"),
            # 检查诱导子图是否连通
            connected = is.connected(induced_subgraph(g, sg))
        )
    })
    
    # 奖励1:purple占优的基础分 + 占优幅度额外奖励
    purple_bonus <- sum(sapply(subgraph_stats, function(st) {
        if (st$purple > st$orange) {
            1 + (st$purple - st$orange)/5  # 基础分1,每多1个purple加0.2分
        } else {
            0
        }
    }))
    
    # 奖励2:连通子图额外加分
    connectivity_bonus <- sum(sapply(subgraph_stats, function(st) {
        if (st$connected) 0.5 else 0
    }))
    
    # 总适应度
    return(purple_bonus + connectivity_bonus)
}

# 运行改进后的遗传算法
ga_result <- ga(
    type = "integer",  # 更换为整数分配类型
    fitness = fitness,
    min = 1,
    max = 5,
    popSize = 100,  # 增大种群规模
    maxiter = 1500,  # 增加迭代次数
    run = 150,
    pmutation = 0.3,  # 提高变异率
    crossover = gaint_spCrossover,  # 适合整数类型的交叉策略
    mutation = gaintMutator,  # 适合整数类型的变异策略
    monitor = FALSE,
    keepBest = TRUE
)

# 补充原代码缺失的绘图函数
plot_subgraphs <- function(solution, idx) {
    partition_colors <- rainbow(5)[solution]
    plot(g, 
         vertex.color = partition_colors,
         vertex.size = 8,
         vertex.label = node_colors,
         main = paste("Solution", idx, "Fitness:", round(ga_result@fitness[idx], 2))
    )
    # 打印子图统计
    subgraphs <- split(1:n_nodes, solution)
    for (i in 1:length(subgraphs)) {
        sg <- subgraphs[[i]]
        purple <- sum(node_colors[sg] == "purple")
        orange <- sum(node_colors[sg] == "orange")
        cat(paste0("Subgraph ", i, " : ", paste(sg, collapse = " "), "\n"))
        cat(paste0("Purple: ", purple, " Orange: ", orange, "\n\n"))
    }
}

# 展示前3个最优解
n_solutions <- 3
solutions <- ga_result@solution[1:n_solutions,]

for (i in 1:n_solutions) {
    cat("Solution", i, "\n")
    cat("Fitness score:", round(ga_result@fitness[i], 2), "\n\n")
    plot_subgraphs(solutions[i,], i)
    cat("\n")
}

修正说明

  • 更换GA类型后,算法可以自由探索任意分区结构,不再局限于垂直/水平分区
  • 优化后的适应度函数同时引导算法满足节点数量约束、purple占优、子图连通性三个核心需求
  • 参数调整提升了算法的全局搜索能力,更容易跳出局部最优解

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 06:50:55