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

使用PyGAD生成HPC集群作业唯一约束点遇问题求助

问题描述

在HPC项目中,我想用PyGAD生成唯一的点集提交给集群作业——因为集群时间成本高,必须避免重复作业;同时作业涉及物理模拟,数值不能出现负数(比如粒子数、长度),得做范围约束。

根据PyGAD文档,allow_duplicate_genes和gene_space参数应该能满足需求,但运行以下代码时,不仅出现大量重复点,还偶尔生成超出gene_space范围的点:

import pygad
import numpy
import itertools

def mock_function(solution, sol_idx):
    return -1 * (solution[0] ** 2 + solution[1] ** 2)
range = [.1, 1.]
param_values = numpy.linspace(range[0], range[1], 10).tolist()
initial_population = list(itertools.product(param_values, param_values))

ga = pygad.GA(num_generations=100,
              num_parents_mating=10,
              gene_type=float,
              gene_space={'low': range[0], 'high': range[1]},
              fitness_func=mock_function,
              initial_population=initial_population,
              mutation_probability=0.2,
              allow_duplicate_genes=False,
              )
ga.run()

new_points = ga.population
unique_points = set([tuple(x) for x in new_points])
print(len(initial_population), len(new_points), len(unique_points))
print(f"Best solution is {ga.best_solution()[0]}.")
for point in new_points:
    for x in point:
        if not range[0] <= x <= range[1]:
            print(f"Point {point} is outside gene_space.")

注:GitHub仓库已有开放Issue称最新版本修复了唯一性问题,但示例中问题仍存在,且有点超出范围。请问我忽略了什么?


问题分析与解决

1. 对allow_duplicate_genes的核心误解

这个参数控制的是单个个体内部的基因是否允许重复(比如一个二维解里两个维度的值能不能相同),完全不是你需要的“种群内不同个体不能重复”。这是导致重复点出现的根本原因——你用错了参数。

2. gene_space约束失效的解决

默认情况下,PyGAD的突变、交叉操作可能会突破gene_space的范围,因为部分遗传操作不会自动截断数值。只需添加keep_genes_within=True参数,就能强制所有操作后的基因都被限制在指定范围内。

3. 实现种群个体唯一性的方案

PyGAD原生没有直接控制种群个体唯一的参数,需要手动处理:

  • 自定义逻辑,在每一代进化后检查并替换重复个体
  • 注意浮点精度问题:直接用tuple(sol)判断重复可能因浮点误差误判,建议先取固定小数位再去重

修改后的示例代码

import pygad
import numpy
import itertools

def mock_function(solution, sol_idx):
    return -1 * (solution[0] ** 2 + solution[1] ** 2)

# 重命名变量避免和内置函数冲突
range_min = .1
range_max = 1.
param_values = numpy.linspace(range_min, range_max, 10).tolist()
initial_population = list(itertools.product(param_values, param_values))

# 确保种群内个体唯一的函数
def ensure_unique_population(population, gene_space):
    unique_pop = []
    seen = set()
    for sol in population:
        # 浮点取6位小数,避免精度误差导致的伪重复
        sol_tuple = tuple(numpy.round(sol, 6))
        if sol_tuple not in seen:
            seen.add(sol_tuple)
            unique_pop.append(sol)
        else:
            # 生成符合约束的新随机个体替换重复项
            new_sol = numpy.random.uniform(gene_space['low'], gene_space['high'], size=len(sol))
            unique_pop.append(new_sol)
    return numpy.array(unique_pop)

ga = pygad.GA(num_generations=100,
              num_parents_mating=10,
              gene_type=float,
              gene_space={'low': range_min, 'high': range_max},
              fitness_func=mock_function,
              initial_population=initial_population,
              mutation_probability=0.2,
              allow_duplicate_genes=False,  # 按需保留,控制单个个体内基因是否重复
              keep_genes_within=True,  # 强制基因不越界
              # 每一代进化后执行唯一性检查
              on_generation=lambda ga: setattr(ga, 'population', ensure_unique_population(ga.population, ga.gene_space))
              )
ga.run()

new_points = ga.population
unique_points = set([tuple(numpy.round(x, 6)) for x in new_points])
print(len(initial_population), len(new_points), len(unique_points))
print(f"Best solution is {ga.best_solution()[0]}.")
for point in new_points:
    for x in point:
        if not range_min <= x <= range_max:
            print(f"Point {point} is outside gene_space.")

关键修改说明

  • 重命名range变量,避免和Python内置函数冲突
  • 添加keep_genes_within=True,彻底解决基因越界问题
  • 新增ensure_unique_population函数,处理种群个体唯一性并解决浮点精度问题
  • 使用on_generation回调,每一代进化后自动执行唯一性检查和替换

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:35:17