pgapack并行遗传算法库的Python封装
项目描述
新闻
2023年10月新闻
为整数添加差分进化
添加负 assortative 繁殖选项
2023年4月新闻
PyPi上最后一次构建对于串行安装是损坏的,它缺少串行版本所需的mpi_stub.c。并行安装仍然是可能的,所以我没注意到,抱歉!
将MPI_Abort添加到包装器中,它在evaluate方法中发生异常时调用
pga.MPI_Abort (errcode)
有关如何在运行与MPI部分使用它来在发生异常时终止MPI运行的信息,请参阅下文。
2022年12月新闻:添加回归测试并更新到新的上游,包括几个错误修复。还包括包装器中的几个错误修复。
2022年10月新闻:添加用户定义的数据类型。在examples/gp中使用用户定义的数据类型来实现遗传编程(我们用树数据结构表示表达式)。这使用pgapack中的新序列化API将Python pickle表示传递到对等MPI进程。还纳入了pgapack的最新更改,这优化了重复检查。这对于遗传编程示例中的大型种群大小很有兴趣。请注意,gene_difference方法已重命名为gene_distance。
新闻 08-2022:Epsilon约束优化以及一个保留排列的交叉变体(因此,对于整数基因,基因可以表示排列)。
新闻 03-2022:尝试使其在Windows上可安装。这涉及到代码中的某些变通方法,因为可视编译器不支持某些C99结构。
新闻 01-2022:这个版本使用了NSGA-III进行多次评估(注意额外的“I”)。
新闻 12-2021:这个版本从您的目标函数中包装了多个评估值:现在您可以返回多个值,用于约束(必须在优化目标之前满足)或用于与Nondominated Sorting Genetic Algorithm V.2(NSGA-II)的多目标优化。您可以同时使用多目标优化和约束。
新闻:这个版本包装了差分进化方法(这是一个相当老的方法,但在pgapack中是新生成的)。
简介
PGAPy是PGAPack的包装器,一个并行遗传算法库(参见PGAPack Readme),由D. Levine编写,属于数学与计算机科学部,Argonne国家实验室。该库是用C语言编写的。PGAPy为此库提供了Python的包装,以便使用。原始的PGAPack库虽然已经相当老,但它是目前最完整、最精确(虽然这不是将它们包装到Python时的主要关注点)的遗传算法实现之一,具有许多用于实验的铃声和口哨。它还显示出惊人的少量错误。除了正常的“串行”版本外,它还支持通过消息传递接口MPI进行并行执行。这就是为什么我也想在Python中使用它。
要开始使用,您需要PGAPack库,尽管它现在与PGApy捆绑在一起,但要安装一个并行版本,您目前需要为所选的MPI库预编译的PGAPack。有关详细信息,请参阅安装部分。
目前对PGAPy的文档不多。您真的、绝对需要阅读随PGAPack一起提供的文档。PGAPack用户指南现在与PGAPy一起提供。它与一些示例一起安装,安装位置由Python安装程序决定(通常在Linux上为/usr/local/share)。
原始的PGAPack库仍然可以从PGAPack ftp站点下载,它使用ANSI C编写,但可能无法与最新的MPI版本兼容。它也无法与最新的PGAPy版本一起工作。请注意,此版本不再积极维护。我在GitHub上启动了一个PGAPack分支,其中我已经将库移植到最新的MPI标准,并修复了一些文档中的小不一致之处。我还实现了一些新功能,特别是选择方案的增强,称为受限锦标赛替换 [1],[2],[4],以及最近,差分进化策略 [5],[6]。此外,此版本现在支持多目标优化与NSGA-II [7]以及多目标优化与NSGA-III [8],[9],并且支持Epsilon约束方法 [10]。
注意:当使用NSGA_III替换进行多(或多)目标优化时,您需要执行以下操作之一:
在所有轴偏移1的超平面上设置参考点。这些参考点可以通过方便的函数pga.das_dennis获得,它使用I. Das和J. E. Dennis最初发布的算法创建一个规则的参考点集 [12]。然后,将这些点作为参数reference_points传递给PGA构造函数。
有关使用示例和用户指南的参考文献,请参阅examples/dtlz2.py。该函数获取目标空间的维数(num_eval减去num_constraint)和要使用的分区数。
或者使用reference_directions参数设置参考方向(在目标空间中),使用refdir_partitions参数设置这些方向的数量(参见上文的das_dennis,这使用Das/Dennis点内部),并使用参数refdir_scale设置一个比例因子。
您可以同时设置这两个参数,这些参数不是互斥的。
我主要在Linux上测试pgapy。但最近我也让它能在Windows上运行,但我并不是非常积极地测试Windows。如果您在Windows上运行它,无论是成功还是不成功,请让我知道。
如上所述,您可以在GitHub上找到我的PGAPack分支,该存储库包含git中的三个上游版本作为版本,并包含有关支持更新的MPI版本和文档更新的某些更新。我还将补丁包含在软件包的Debian维护者Dirk Eddelbuettel的git存储库中。我正在积极维护该分支,添加新功能和错误修复。
为了帮助您开始,我在“examples”中包含了几个非常简单的示例,例如,one-max.py实现了类似于PGAPack文档中的一个“Maxbit”示例。这些示例灵感来源于《Python遗传算法》一书,但都是从头编写的,不包含书中的任何代码。这些示例说明了几个要点。
您实现遗传算法的类需要从pga.PGA(pga是PGAPy包装模块)继承。
您需要定义一个名为evaluate的评估函数,该函数返回一个表示给定基因适应度的数字序列。它通过使用get_allele方法获取基因的等位基因值,这些参数是p和pop。有关更多详细信息,请参阅PGAPack文档。您的函数返回的评估次数由构造函数参数num_eval定义,此参数的默认值为1。如果您的评估函数不返回多个评估(使用默认的num_eval设置),则可以返回一个只有一个元素的序列或单个返回值。
当使用多个评估时,这些评估可以用于约束(默认)或多目标优化。在后一种情况下,约束的数量(默认情况下比使用参数num_eval设置的评估次数少一个)必须设置为至少为两个目标留下两个评估的数字。可以使用参数num_constraint设置约束的数量。在多目标优化中使用时,您需要一个两种替换类型之一PGA_POPREPL_NSGA_II或PGA_POPREPL_NSGA_III,使用pop_replace_type参数设置。
您可以定义额外的函数来覆盖PGAPack库的内置函数,例如print_string的示例。请注意,我们可以调用我们的PGA超类的原始print_string方法。以相同的方式,您可以实现,例如,您自己的交叉方法。
类的构造函数需要定义基因类型,在示例中我们使用了int和bool内置数据类型。
基因的长度需要在构造函数中给出。
我们通常希望最大化评估函数返回的数字,如果您想最小化,将参数maximize设置为False。
对于非二进制基因,我们可以定义一个初始化值的数组,每个条目包含一个包含下限和上限的序列。该数组必须与基因的长度相同。请注意,上限包含在可能值的范围内(与python范围运算符不同,但与PGAPack定义兼容)。
在类的构造函数中,我们可以添加遗传算法的参数。并非所有PGAPack参数都已包装,目前您需要查阅PGAPy的源代码以找出哪些参数已包装。在示例中,我们定义了几个打印选项。
最后,使用run方法启动遗传算法。
PGAPy的命名约定
当您扩展PGAPy时——请记住并非所有PGAPack函数都已包装,您可能需要额外的函数——在做出更改时,您应该坚持我的命名约定。以下命名约定用于包装器
PGAPack的常量,如PGA_REPORT_STRING,按原样以大写形式使用。这些常量可以直接从包装模块导入。到目前为止,并非所有常量都已包装,如果您需要更多,请将它们添加到pgamodule.c中的constdef数组,并发送补丁给我。
对于pga.PGA类的各种方法,我已经移除了PGAPack中使用的全局< span class="docutils literal">PGA前缀,并将原始函数名中的大写单词之间用下划线连接,转换为小写,例如< span class="docutils literal">PGARun变为< span class="docutils literal">run,< span class="docutils literal">PGACheckStoppingConditions变为< span class="docutils literal">check_stopping_conditions。但是,如果名称中包含“GA”(表示“遗传算法”),则例外,所以< span class="docutils literal">PGASetMaxGAIterValue变为< span class="docutils literal">max_GA_iter。
尽可能地将PGAPack需要为每种数据类型分别提供的函数合并为单个类方法,因此< span class="docutils literal">PGAGetBinaryAllele、< span class="docutils literal">PGAGetCharacterAllele、< span class="docutils literal">PGAGetIntegerAllele、< span class="docutils literal">PGAGetRealAllele都变为< span class="docutils literal">get_allele。同样,对于< span class="docutils literal">set_allele也是如此。
每当PGAPack中的名称带有“Value”或“Flag”后缀时,我都会省略它,因此< span class="docutils literal">PGAGetFitnessCmaxValue变为< span class="docutils literal">fitness_cmax,< span class="docutils literal">PGAGetMutationAndCrossoverFlag变为< span class="docutils literal">mutation_and_crossover。唯一的例外是两个函数< span class="docutils literal">PGAGetMutationRealValue和< span class="docutils literal">PGAGetMutationIntegerValue,它们变为< span class="docutils literal">mutation_value,而不仅仅是< span class="docutils literal">mutation。
某些字段可以接受多个值(它们通过按位或整数常量实现,在Python中,它们指定为常量的列表或元组)。如果这些字段在PGAPack中不是复数(如果不是复数),则将它们转换为复数,例如,< span class="docutils literal">PGASetStoppingRuleType变为< span class="docutils literal">stopping_rule_types。
包装程序中的内部方法名称以PGA_开头,因此类方法< span class="docutils literal">set_allele通过C函数< span class="docutils literal">PGA_set_allele在< span class="docutils literal">pgamodule.c中实现。
构造函数参数
PGAPack有很多用于设置参数的< span class="docutils literal">PGASet和< span class="docutils literal">PGAGet函数。这些函数一方面反映在构造函数参数中,另一方面反映在(通常是只读的,但请参见下文)< span class="docutils literal">PGA对象的属性中。以下表格概述了所有原始PGAPack名称和Python包装器的名称。对于PGAPack名称,我只列出了< span class="docutils literal">PGASet函数,在许多情况下,有一个相应的< span class="docutils literal">PGAGet函数。如果构造函数参数存在相应的只读属性,则在“Prop”列中指示。在某些情况下,由于PGAPack中没有实现相应的< span class="docutils literal">PGAGet函数,因此属性缺失,在其他情况下,返回具有PGApy中符号常量的数值在意义上并不太多。
属性与构造函数参数具有相同的名称。有一些属性没有相应的构造函数参数,即< span class="docutils literal">eval_count属性(返回函数评估的计数),返回当前GA代数的< span class="docutils literal">GA_iter属性,以及返回当前进程MPI排名的< span class="docutils literal">mpi_rank属性(这归入PGAGetRank)。
在类型列中,我列出了Python类型。如果类型后跟一个数字,则表示该类型的多个项目被指定(Python中的序列)。一些条目包含“sym”,这些是具有符号常数的整数值,值“msym”表示可以给出由符号常数的列表表示的几个值。特殊情况是PGASetRealInitRange、PGASetRealInitPercent、PGASetIntegerInitRange函数。这些为基因的每个等位基因取两个值。在Python中,这是一个2元组的序列。请注意,这意味着可以为每个等位基因有不同的允许值范围。
num_eval属性是特殊的:由于C编程语言的限制,在C中进行多次评估时,第一个评估作为evaluate函数的函数返回值返回,所有其他参数都返回在一个辅助数组中。PGAPack指定要返回的辅助评估次数。在Python中,评估函数可以始终返回一个评估值的序列,而num_eval比PGAGetNumAuxEval返回的值多1。默认情况下,num_eval为1。
前两个(必需)构造函数参数是基因的类型(这需要一个Python类型,例如,对于二进制基因组使用bool,对于整数基因组使用int)和长度。请注意,string_length通过length参数隐式设置。也可以使用Python内置的len函数将string_length作为PGA对象的长度的值。
现在也可以在优化器运行期间设置一些属性。这些目前是crossover_prob、epsilon_exponent、multi_obj_precision、p_tournament_prob和uniform_crossover_prob。只需将优化器(PGA.pga对象的子代)的成员变量赋值即可。
PGAPack名称 |
构造函数参数 |
类型 |
属性 |
---|---|---|---|
PGASetCrossoverBoundedFlag |
crossover_bounded |
int |
yes |
PGASetCrossoverBounceBackFlag |
crossover_bounce_back |
int |
yes |
PGASetCrossoverSBXEta |
crossover_SBX_eta |
float |
yes |
PGASetCrossoverSBXOncePerString |
crossover_SBX_once_per_string |
int |
yes |
PGASetCrossoverProb |
crossover_prob |
float |
yes |
PGASetCrossoverType |
crossover_type |
sym |
no |
PGASetDEAuxFactor |
DE_aux_factor |
double |
yes |
PGASetDECrossoverProb |
DE_crossover_prob |
double |
yes |
PGASetDECrossoverType |
DE_crossover_type |
sym |
no |
PGASetDEDither |
DE_dither |
double |
yes |
PGASetDEDitherPerIndividual |
DE_dither_per_individual |
bool |
yes |
PGASetDEJitter |
DE_jitter |
double |
yes |
PGASetDENumDiffs |
DE_num_diffs |
int |
yes |
PGASetDEProbabilityEO |
DE_probability_EO |
double |
yes |
PGASetDEScaleFactor |
DE_scale_factor |
double |
yes |
PGASetDEVariant |
DE_variant |
sym |
yes |
PGASetEpsilonExponent |
epsilon_exponent |
float |
yes |
PGASetEpsilonGeneration |
epsilon_generation |
int |
yes |
PGASetEpsilonTheta |
epsilon_theta |
int |
yes |
PGAGetEvalCount |
eval_count |
int |
yes |
PGASetFitnessCmaxValue |
fitness_cmax |
float |
yes |
PGASetFitnessMinType |
fitness_min_type |
sym |
yes |
PGASetFitnessType |
fitness_type |
sym |
yes |
PGAIntegerSetFixedEdges |
fixed_edges |
no |
|
PGAIntegerSetFixedEdges |
fixed_edges_symmetric |
bool |
no |
PGAGetGAIterValue |
GA_iter |
int |
yes |
PGASetIntegerInitPermute |
integer_init_permute |
int2 |
no |
PGASetIntegerInitRange |
init |
no |
|
PGASetMaxFitnessRank |
max_fitness_rank |
float |
yes |
PGASetMaxGAIterValue |
max_GA_iter |
int |
yes |
PGASetMaxNoChangeValue |
max_no_change |
int |
no |
PGASetMaxSimilarityValue |
max_similarity |
int |
yes |
PGASetMixingType |
mixing_type |
sym |
no |
PGASetMultiObjPrecision |
multi_obj_precision |
int |
yes |
PGASetMutationAndCrossoverFlag |
mutation_and_crossover |
int |
yes |
PGASetMutationBounceBackFlag |
mutation_bounce_back |
int |
yes |
PGASetMutationBoundedFlag |
mutation_bounded |
int |
yes |
PGASetMutationIntegerValue |
mutation_value |
int |
yes |
PGASetMutationOrCrossoverFlag |
mutation_or_crossover |
int |
yes |
PGASetMutationPolyEta |
mutation_poly_eta |
float |
yes |
PGASetMutationPolyValue |
mutation_poly_value |
float |
yes |
PGASetMutationProb |
mutation_prob |
float |
yes |
PGASetMutationRealValue |
mutation_value |
float |
yes |
PGASetMutationType |
mutation_type |
sym |
no |
PGASetNAMWindowSize |
nam_window_size |
int |
yes |
PGASetNoDuplicatesFlag |
no_duplicates |
int |
no |
PGASetNumAuxEval |
num_eval |
int |
yes |
PGASetNumConstraint |
num_constraint |
int |
yes |
PGASetNumReplaceValue |
num_replace |
int |
yes |
PGASetPopSize |
pop_size |
int |
yes |
PGASetPopReplaceType |
pop_replace_type |
sym |
no |
PGASetPrintFrequencyValue |
print_frequency |
int |
yes |
PGASetPrintOptions |
print_options |
msym |
no |
PGASetPTournamentProb |
p_tournament_prob |
float |
yes |
PGASetRandomizeSelect |
randomize_select |
int |
yes |
PGASetRandomSeed |
random_seed |
int |
yes |
PGAGetRank |
mpi_rank |
int |
yes |
PGASetRealInitRange |
init |
no |
|
PGASetRealInitPercent |
init_percent |
no |
|
PGASetReferenceDirections |
refdir_partitions |
int |
no |
PGASetReferenceDirections |
refdir_scale |
double |
no |
PGASetReferenceDirections |
reference_directions |
no |
|
PGASetReferencePoints |
reference_points |
no |
|
PGASetRestartFlag |
restart |
int |
yes |
PGASetRestartFrequencyValue |
restart_frequency |
int |
yes |
PGASetRTRWindowSize |
rtr_window_size |
int |
yes |
PGASetSelectType |
select_type |
sym |
no |
PGASetStoppingRuleType |
stopping_rule_types |
msym |
no |
PGASetStringLength |
string_length |
int |
yes |
PGASetSumConstraintsFlag |
sum_constraints |
int |
yes |
PGASetTournamentSize |
tournament_size |
int |
yes |
PGASetTournamentWithReplacement |
tournament_with_replacement |
int |
yes |
PGASetTruncationProportion |
truncation_proportion |
float |
yes |
PGASetUniformCrossoverProb |
uniform_crossover_prob |
float |
yes |
注意:mutation_or_crossover 和 mutation_and_crossover 参数已弃用,请使用 mixing_type 代替!
PGA对象方法
以下是在遗传搜索运行期间可以使用的方法。使用 run 方法来启动搜索。这可以用于,例如,在自定义 endofgen 方法中的爬山过程中设置等位基因。请注意,某些方法仅适用于某些基因类型,例如 encode_int_ 方法只能用于二进制等位基因(它们将整数值编码为二进制或灰度代码表示形式到基因中)。其他方法根据基因类型接收或返回不同的类型,例如 get_allele 或 set_allele,它们根据基因类型调用不同的后端函数。使用 set_random_seed 方法,可以重新播种随机数生成器。通常最好在(在)开始时(之前)通过在构造函数中指定 random_seed 来播种生成器。有关更多详细信息,请参阅用户指南。方法 get_evaluation 将返回单个评估的双精度值和一个双精度元组(当 num_eval > 1 时)
方法 |
参数 |
返回值 |
---|---|---|
check_stopping_conditions |
如果应停止则为 true |
|
encode_int_as_binary |
p, pop, frm, to, val |
None |
encode_int_as_gray_code |
p, pop, frm, to, val |
None |
encode_real_as_binary |
p, pop, frm, to l, u, val |
None |
encode_real_as_gray_code |
p, pop, frm, to l, u, val |
None |
euclidian_distance |
p1, pop1 p2, pop2 |
float |
fitness |
pop |
None |
get_allele |
p, pop, index |
等位基因值 |
get_best_index |
pop |
最佳字符串的索引 |
get_best_report_index |
pop, idx |
具有 idx 的最佳评估的索引 |
get_evaluation |
p, pop |
p 的评估 |
get_evaluation_up_to_date |
p, pop |
如果是最新版本则为 true |
get_fitness |
p, pop |
p 的适应度(浮点数) |
get_gene |
p, pop |
获取基因(用户数据类型) |
get_int_from_binary |
p, pop, frm, to |
int |
get_int_from_gray_code |
p, pop, frm, to |
int |
get_iteration |
已弃用,使用 GA_iter |
|
get_real_from_binary |
p, pop, frm, to, l, u |
float |
get_real_from_gray_code |
p, pop, frm, to, l, u |
float |
random01 |
0到1之间的浮点数 |
|
random_flip |
概率 |
0或1 |
random_gaussian |
均值,标准差 |
float |
random_interval |
l, r |
介于l和r之间的整数 |
random_uniform |
l, r |
介于l和r之间的浮点数 |
run |
None |
|
select_next_index |
pop |
选中的个体索引 |
set_allele |
p, pop, i, value |
None |
set_evaluation |
p, pop, value |
None |
set_evaluation_up_to_date |
p, pop, status |
None |
set_gene |
p, pop, gen |
设置基因(用户数据类型) |
set_random_seed |
种子 |
None(使用构造函数!) |
用户方法
PGAPack 具有用户函数的概念。这允许自定义遗传算法的不同区域。在 Python 中,它们实现为可以在派生类中更改的方法。必须在派生类中实现的方法之一是 evaluate 函数(尽管技术上它不是 PGAPack 中的用户函数)。它解释基因并返回评估值或评估值的序列,如果您设置了 num_eval 构造函数参数。 PGAPack 从原始评估值计算适应性。对于某些方法,可以向上调用 PGA 类,对于某些方法则不可行(并且在大多数情况下不合理)。请注意,对于 stop_cond 方法,可以使用以下方式调用标准停止条件检查
self.check_stopping_conditions()
以下表格列出了可覆盖的方法及其参数(对于函数签名,省略了第一个参数 self)。请注意,在 PGAPack 中,还有其他用户函数,这些函数对于用户定义的数据类型是必需的,但目前尚未在 Python 中公开。在函数签名中,p 表示个体的索引,pop 表示种群。如果指定了多个个体(例如,对于交叉),则可以跟一个数字。对于交叉,c1 和 c2 表示目标个体(子代)。突变方法的 probability 是介于 0 和 1 之间的浮点值。请记住计算发生突变的数量,并为此返回该值!
方法 |
调用签名 |
返回值 |
向上调用 |
---|---|---|---|
check_duplicate |
p1, pop1, p2, pop2 |
如果重复则返回 True |
no |
stop_cond |
返回 True 以停止 |
no |
|
crossover |
p1, p2, p_pop, c1, c2, c_pop |
None |
no |
endofgen |
None |
no |
|
evaluate |
p, pop |
浮点数序列 |
no |
gene_distance |
p1, pop1, p2, pop2 |
float |
no |
哈希值 |
p, pop |
int |
no |
initstring |
p, pop |
None |
no |
mutation |
p, pop, propability |
mutations |
no |
pre_eval |
pop |
None |
no |
print_string |
file, p, pop |
None |
yes |
常量
以下 PGAPack 常量可用
常量 |
描述 |
---|---|
PGA_CROSSOVER_EDGE |
排列的边缘交叉 |
PGA_CROSSOVER_ONEPT |
一点交叉 |
PGA_CROSSOVER_SBX |
模拟二进制交叉 |
PGA_CROSSOVER_TWOPT |
两点交叉 |
PGA_CROSSOVER_UNIFORM |
均匀交叉 |
PGA_FITNESSMIN_CMAX |
通过减去最坏值映射适应性 |
PGA_FITNESSMIN_RECIPROCAL |
通过倒数映射适应性 |
PGA_FITNESS_NORMAL |
适应性线性归一化 |
PGA_FITNESS_RANKING |
适应性线性排名 |
PGA_FITNESS_RAW |
恒等适应性函数 |
PGA_MUTATION_CONSTANT |
通过添加/减去常数进行突变 |
PGA_MUTATION_GAUSSIAN |
通过选择高斯分布进行突变 |
PGA_MUTATION_PERMUTE |
突变交换两个随机基因 |
PGA_MUTATION_POLY |
多项式突变 |
PGA_MUTATION_RANGE |
用初始范围内的统一选择替换基因 |
PGA_MUTATION_UNIFORM |
从区间均匀变异 |
PGA_NEWPOP |
新种群符号常量 |
PGA_OLDPOP |
旧种群符号常量 |
PGA_POPREPL_BEST |
种群替换最佳字符串 |
PGA_POPREPL_NSGA_II |
使用NSGA-II替换进行多目标优化 |
PGA_POPREPL_NSGA_III |
使用NSGA-III替换进行多目标优化 |
PGA_POPREPL_PAIRWISE_BEST |
比较新旧种群中相同索引 |
PGA_POPREPL_RANDOM_NOREP |
种群替换随机不重复 |
PGA_POPREPL_RANDOM_REP |
种群替换随机重复 |
PGA_POPREPL_RTR |
限制性锦标赛替换 |
PGA_REPORT_AVERAGE |
报告平均评估 |
PGA_REPORT_HAMMING |
报告汉明距离 |
PGA_REPORT_OFFLINE |
离线报告 |
PGA_REPORT_ONLINE |
在线报告 |
PGA_REPORT_STRING |
报告字符串 |
PGA_REPORT_WORST |
报告最差评估 |
PGA_SELECT_LINEAR |
按种群顺序返回个体 |
PGA_SELECT_PROPORTIONAL |
适应度比例选择 |
PGA_SELECT_PTOURNAMENT |
二进制概率锦标赛选择 |
PGA_SELECT_SUS |
随机通用选择 |
PGA_SELECT_TOURNAMENT |
锦标赛选择 |
PGA_SELECT_TRUNCATION |
截断选择 |
PGA_STOP_MAXITER |
在最大迭代次数时停止 |
PGA_STOP_NOCHANGE |
在最大代数没有变化时停止 |
PGA_STOP_TOOSIMILAR |
当个体过于相似时停止 |
用户定义数据类型
PGAPy的最新版本支持用户定义数据类型。只需定义您的数据类型,并将其作为第二个参数传递给PGA构造函数。框架将在通过MPI(如果您运行的是并行版本)传输数据时处理数据的序列化。
如果通过no_duplicates构造函数参数启用重复检查,则您的数据类型需要定义一个__hash__方法(除非Python默认的哈希方法满足您的需求)。
用户定义的数据类型不使用等位基因,因此正常的get_allele(和set_allele)方法不可用。相反,可以使用get_gene方法检索整个个体,并使用set_gene方法设置。
使用用户数据类型,您需要定义以下方法
check_duplicate (self, p1, pop1, p2, pop2)如果您启用交叉参数no_duplicates的重复检查。当两个个体是重复项时应返回True。使用get_gene检索在种群pop1和pop2中的个体p1和p2的基因。
crossover (self, p1, p2, ppop, c1, c2, cpop)对于交叉操作,使用get_gene获取在生成ppop中的父代p1和p2的基因,并使用set_gene设置在生成cpop中的子代基因c1和c2。
initstring (self, p, pop)用于初始化给定的字符串,在该方法中使用set_gene将您的对象设置为基因。
使用mutation(self, p, pop, pm)进行变异操作。这个方法应该返回执行变异的数量。如果启用重复检查,框架将反复调用变异算子,将重复的个体变异为非重复的另一个个体。这使用您变异方法的返回值。如果您的变异算子在重复检查启用时偶尔不返回非零的变异次数,您将进入一个无限循环。pm参数给出变异概率。使用get_gene来检索要变异的个体,使用set_gene在变异后更新此个体。
要打印基因对象,使用print_string(self, file, p, pop),使用get_gene来检索要打印的个体。
对于这些方法,通常一个好的做法是永远不要就地修改一个个体:这个个体可能会被反复用于遗传操作(例如变异和交叉),所以在修改它时,您将在后续的遗传操作中产生错误的结果。要复制数据结构,通常使用python模块中的deepcopy函数。
除了上述方法之外,您可能希望使用stop_cond方法定义一个停止规则,或者使用hash方法覆盖哈希计算的方式。计算哈希的默认方法是调用hash(gene),其中gene是用户定义的数据类型的一个对象。其他可能使用的方法是endofgen方法、gene_distance方法(例如,在使用带有PGA_POPREPL_RTR的受限锦标赛选择时),或者pre_eval方法。
有关用户定义数据类型的示例在examples/gp中:这实现了使用树数据结构的遗传编程。请注意,gp.py中的Node类有一个__hash__方法,它通过树的序列化构建哈希(对于具有相同树结构的个体来说是相同的)。
缺少的功能
如前所述,PGAPack中并非所有函数和常量都已被封装——对于许多应用,给定的集应该足够。如果您需要额外的函数,您可能希望封装这些函数并发给我一个补丁。
报告错误
请使用Sourceforge错误跟踪器或Github错误跟踪器,并
提供关于您认为的正确行为的简短描述
提供观察到的行为的描述
告诉我您确切做了什么。
如果您可以发布您的源代码,这将使我为您调试错误变得容易得多
资源
从Sourceforge主页获取项目信息和下载
或从Github检出
或直接通过pypi安装
安装
PGApy,正如其名所示,支持并行化遗传算法的评估函数。这使用消息传递接口(MPI)标准。
要安装一个串行版本(不使用MPI进行并行编程),您只需使用pip从pypi安装即可。或者,当您已解压或检出源代码时,您可以使用以下方式安装:
python3 setup.py install --prefix=/usr/local
如果您想使用MPI(消息传递接口)库的并行版本,您首先需要安装PGAPack的并行版本。最简单的方法是使用来自github的pgapack deb包构建器。克隆此存储库,检出分支master,安装构建依赖项,它们在文件debian/control中列出,并使用以下命令构建deb包:
dpkg-buildpackage -rfakeroot
这将为debian中所有受支持的MPI库构建pgapack deb包,目前这些是mpich、openmpi和lam。除了MPI库外,还构建了pgapack库的串行版本。接下来,安装pgapack包和所选的MPI后端库。如果您没有对MPI库的偏好,libpgapack-openmpi是使用Debian默认MPI库偏好的包。
安装PGAPack的并行版本后,您可以通过以下方式安装PGApy:设置PGA_PARALLEL_VARIANT环境变量(mpich、openmpi或lam之一)并将PGA_MODULE设置为module_from_parallel_install。最后,调用设置,例如:
export PGA_PARALLEL_VARIANT=openmpi export PGA_MODULE=module_from_parallel_install python3 setup.py install --prefix=/usr/local
请注意,这同样适用于pip install,即在安装PGAPack的并行版本后,您可以直接使用pip安装。
export PGA_PARALLEL_VARIANT=openmpi export PGA_MODULE=module_from_parallel_install pip install pgapy
或者根据您的系统上pip的安装方式选择其他方法。
python3 -m pip install pgapy
如果您的MPI库安装在另一个位置,您应该研究setup.py中的Extension配置,以便得出适合您的安装的扩展定义。如果您的安装对更多人来说很有趣,您可以随意提交一个补丁,将您的扩展配置添加到标准的setup.py。
关于较新版本的Python
较新版本的Python已弃用安装到系统Python版本中,即使在/usr/local。您仍然可以本地构建pgapy包并使用安装程序安装。在Debian Linux上,您需要安装以下包:
apt-get install python3-pip python3-dev python3-toml \ python3-build python3-installer python3-venv python3-sphinx netpbm
然后您可以在本地构建并安装。
python3 -m build python3 -m installer dist/*.whl
更好的方法是,从github克隆我的releasetool包到pgapy的parallel目录中,并使用以下命令构建:
git clone https://github.com/schlatterbeck/releasetool.git
这也会生成一个包含正确版本号的Version.py文件。如果您想安装并行版本,您应该在构建之前设置环境变量
make dist
。
export PGA_PARALLEL_VARIANT=openmpi export PGA_MODULE=module_from_parallel_install
。
使用MPI运行
要使用MPI运行并行版本,必须安装并行版本,请参阅上面安装部分。
对于串行版本,PGAPy确保在evaluate函数中发生异常时终止优化。目前框架不支持将信息返回给rank-0 MPI主进程,因此对于MPI不是这种情况。一个解决方案如下:将您的evaluate方法重命名为_evaluate,并在包装_evaluate的新evaluate方法中捕获异常。如果发生异常,调用MPI_Abort。
import traceback import sys ... def evaluate (self, p, pop): try: return self._evaluate (p, pop) except Exception: # Optionally log exception here print (traceback.format_exc ()) pga.MPI_Abort (1) sys.exit (1)
测试
对于测试,最好在安装之前本地构建
python3 setup.py build_ext --inplace
之后,您在本地目录中将有pga.*.so文件。现在您可以使用以下命令运行测试:
python3 -m pytest test
该命令运行所有测试,可能需要一段时间。请注意,测试在examples目录中大多数示例使用不同的命令行参数运行(如果可用)。为了在单个(Python-)进程中执行多次优化运行,我们必须显式调用MPI_Init(而不是依赖PGAPack隐式调用它)。这是因为MPI_Init可能在每个进程中只被调用一次。在test/conftest.py中的固定函数中处理了MPI_Init和MPI_Finalize的调用。
覆盖率
对于Python示例,覆盖率可以使用以下方法计算:
python3 -m pytest --cov examples test
或更详细,包括未测试的行:
python3 -m pytest --cov-report term-missing --cov examples test
目前,对pgamodule.c中的C代码进行覆盖率分析仅在Linux上可行——至少,由于我正在Linux上开发,这是我找到包括C代码在内的覆盖率分析方法的结构。为了进行覆盖率分析编译:
export CFLAGS=-coverage python3 setup.py build_ext --inplace
这将创建一个以.gcno结尾的文件,位于build目录下,通常在x86_64架构上使用python3.9时,类似于build/temp.linux-x86_64-3.9。运行测试将创建以.gcda结尾的统计数据文件。这些是GNU分析器gcov的数据文件。从这些文件中,可以生成可以浏览器查看的.html文件。
lcov --capture --directory . --output-file coverage.info genhtml coverage.info --output-directory coverage_out
请注意,lcov程序是Linux发行版的一部分。
在MPI下运行
测试可以直接在MPI下运行。请注意,目前pytest的--with-mpi选项不支持。此选项假设使用mpi4py包。但是,pgapy只使用来自pgapack的调用,而pgapack会调用MPI。
在MPI下运行使用:
mpirun $MPI_OPTIONS python3 -m pytest test
MPI_OPTIONS可以是,例如:
MPI_OPTIONS=--machinefile ~/.mpi-openmpi --np 8
这将使用位于您主目录中的openmpi机器定义文件和八个进程。
在MPI下运行特别有用,可用于确定C代码覆盖率。假设已安装并行版本的openmpi,代码可以编译为:
PGA_PARALLEL_VARIANT=openmpi PGA_MODULE=module_from_parallel_install export CFLAGS=-coverage python3 setup.py build_ext --inplace
请注意,覆盖率分析使用在构建目录中的文件,这些文件需要在启动并行版本之前存在。否则,每个并行实例都会尝试创建覆盖率文件,导致竞争条件。一旦覆盖率文件就绪,覆盖率框架将确保适当的锁定,以便没有两个进程同时写入同一个覆盖率文件。
通过首先在没有MPI的情况下运行测试,然后以MPI下多个进程的数量运行相同的版本来创建覆盖率文件最佳。在MPI下运行表明,pgamodule.c中的序列化和反序列化代码被调用。
截至目前,我们得到:
Lines: 1423 1475 96.5 % Functions: 131 133 98.5 %
参考文献
变更
版本 2.4:新上游
包裹负关联交配
允许差分进化用于整数基因
上游修复了与差分进化、RTR种群替换和重复避免的功能交互错误
添加选项在皇家道路示例中使用负关联交配
版本 2.2.2:添加pyproject.toml
添加pyproject.toml –遗憾的是,目前似乎无法在pyproject.toml中描述二进制模块,特别是通过环境变量实现的变体选择,这在setup.py中目前实现
版本 2.2.1:MPI_Abort
将MPI_Abort添加到包装器中
在发布中包含mpi_stub.c(如果设置了某些环境变量,请参见上述安装部分)
版本 2.2:模块目录
将pga C模块放入pga模块中
向pga添加几个仅限Python的模块
pga.__init__导出所有内容,以确保兼容性
pga.random包含基于pgapack随机数生成器的Python Random类
版本 2.1:回归测试
在测试期间发现的PGAPack错误修复
Python包装器的错误修复
大量测试,覆盖包装器C代码 > 90%
版本 2.0:用户定义数据类型
实现用户定义数据类型,请注意,您的数据类型可以是可变大小的,例如,树数据结构。框架负责序列化数据类型,并在使用并行版本时将其传输到远程MPI进程。
当使用构造函数参数no_duplicates启用重复检查时,底层pgapack代码现在使用散列表。这意味着努力不再是与种群大小成二次关系,而是线性关系。
在examples/gp目录中的遗传编程(GP)示例
将gene_difference方法重命名为gene_distance
版本 1.8:ε约束优化
ε约束优化
多目标优化中打印评估的精度,使用此功能使回归测试在AMD上工作,其中第16位或更小的浮点数差异会导致测试失败
排列交叉
版本号:尽量与pgapack匹配,尽管我们可能在最后一位数上有所不同
版本 1.2:具有NSGA-III的多目标优化
实现NSGA-III
版本 1.1.6:多项式变异和模拟二进制交叉(SBX)
模拟二进制交叉(SBX)
多项式变异
版本 1.1.1-1.1.5:PGAPack 小更新,非 Debian 修复
修复非 Debian 系统的 setup.py
更新到最新的 PGAPack,进行了一些小改动
版本 1.1:增加 NSGA-II 多目标优化
包含最新的 pgapack 版本 1.4
此版本增加了 Deb 等人提出的非支配排序遗传算法版本 2 (NSGA-II) 的多目标优化。这利用了之前引入的选项,可以在目标函数中返回多个值。要使用此功能,您需要将 num_constraint 参数设置为某个值,使得您的评估函数返回的一些函数值作为目标函数值(而不是约束)。请参见 examples/multi.py 中的示例。
版本 1.0:增加约束处理
包含最新的 pgapack 版本 1.3
这增加了辅助评估。现在,如果您在构造函数中将 num_eval 参数设置为大于 1,则评估函数可以返回多个浮点值作为序列。目前,额外的评估值用于约束处理。约束值被最小化。一旦它们达到零或负值,它们就不再计算:所有正约束的总和是整体约束违规。有关详细信息,请参阅 Deb 2000 年的论文,请参阅用户指南进行引用。如果您不使用约束,则您的代码无需更改。
此版本可能会改变优化路径。因此,对于随机数生成器的相同种子,您将得到不同的结果,至少如果在搜索过程中有评估相同(但遗传材料不同)的个体。这是由于 pgapack 中排序函数的改变(它从 C 标准库切换到稳定的排序)。
版本 0.9:允许安装并行版本
将 argv(或 sys.argv)传递给 PGACreate
向 setup.py 添加一个段以允许使用针对 MPI 库编译的 pgapack 变体进行并行安装。目前这需要一个预先安装的 pgapack Debian 软件包。
版本 0.8:修复真实突变中的错误
修复最新 pgapack 中的核心转储问题
版本 0.7:封装有重大变化
现在实现了差分进化,请参阅 minfloat 示例和 pgapack 用户指南。
版本 0.6:封装有重大变化
现在封装使用了 Python 标准建议来创建自定义类。
更新文档
重命名 fitness_cmax(从 fitness_cmax_value)
更好的参数错误检查
版本 0.5:错误修复发布
现在 setup.py 可以正常工作,之前的版本有一个编码问题
封装一些新方法
修复 PGAPack 截断选择中的错误
版本 0.4:捆绑 PGAPack
现在 PGAPack 软件包被包含为一个 git 子模块。默认情况下,我们针对这个库进行构建
许可证修复:该模块长期以来一直包含一个 COPYING 文件,该文件包含 2 条 BSD 许可证。但 setup.py 和 pgamodule.c 的头文件仍包含另一个许可证。这已经被纠正。
版本 0.3:功能增强,错误修复
移植到 Python3,Python2 仍然受支持,许可证更改。
包装器的 C 代码更新以支持 Python2 和 Python3
更新文档
修复在回调方法发生错误时可能导致的内存泄漏
许可证更改:我们现在有 2 条 BSD 许可证(类似于 PGAPack 的 MPICH 许可证),这之前是 LGPL。
版本 0.2:功能增强,错误修复
64 位支持,更多 PGAPack 函数和属性封装,Readme 更新:Sourceforge 标志,更改章节。
64 位架构的错误修复
更多 PGAPack 的函数和属性封装
向 setup.py 添加构建规则,以便进行 PGAPack 的标准安装构建 - 目前需要编辑 setup.py - 这里应使用自动检测,但这将需要我为测试设置一个带有标准安装的 PGAPack 的机器。
按需添加 Sourceforge 标志
为自动化发布添加“变更”章节
将 __module__ 字符串添加到模块 pga 中的类 PGA。现在在 Python 中调用:: help (pga) 将按预期工作,之前没有为包含的模块提供帮助文本
版本 0.1:初始 freshmeat 通告
PGAPy 是一个用于 PGAPack 的包装器,PGAPack 是一个并行遗传算法库,一个功能强大的遗传算法库。PGAPy 使用 Python 封装了此库。Pgapack 是最具完整性和精确性的遗传算法实现之一,具有许多用于实验的功能。
初始发布
项目详情
PGAPy-2.4.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 00d0a95dd2f36494749fc5e7863549993b1cd48743bf0343265b07fd3f997475 |
|
MD5 | 10b6b9e5b4a6995c818b96010ba7a79a |
|
BLAKE2b-256 | 8d1a722310703d92ad2be2fd6fc6267218345e94050b70a864ca8a5f479c2e4f |