尽管我知道这个问题在很久以前就已经提出了,但我认为值得提供更多关于如何解决此类问题的细节。
遗传算法需要进化算子才能工作。分配中的提示对我们来说是一个二元基因型,用于每一代的采样、交叉和变异。但是,表型是已转换为整数值的值。根据表型计算客观值。
对二进制值进行操作的遗传算法的一种可能设置是使用随机二进制采样、统一交叉和位翻转突变。在下面的示例中,我以这种方式实现了您问题中所述的问题。为此,我使用了进化(多目标)优化框架pymoo,因为它已经提供了实现开箱即用的遗传算法所需的一切(免责声明:我是主要开发人员的pymoo)。更多信息和pymoo的入门指南可以在here找到。
您的问题的最佳选择在于 sin 函数的最大值。考虑到 sin 函数仅从 0 到 pi,最大值为 pi/2。这对应于整数值的 128 和二进制表示的 10000000。
以下使用 pymoo (0.4.1) 的源代码可以相当快地解决您的测试问题。
二进制变量
import numpy as np
from pymoo.algorithms.so_genetic_algorithm import GA
from pymoo.factory import get_sampling, get_crossover, get_mutation
from pymoo.model.problem import Problem
from pymoo.optimize import minimize
class MyProblem(Problem):
def __init__(self):
super().__init__(n_var=8,
n_obj=1,
n_constr=0,
xl=0,
xu=1)
def _evaluate(self, x, out, *args, **kwargs):
# get the number of variables to be used
n = self.n_var
# create the value of each binary value, e.g. 128, 64, 32, 16, 8, 4, 2, 1
val = np.full(n, 2) ** np.arange(n)[::-1]
# convert the input to the corresponding integer value
x_as_int = (x * val).sum(axis=1)
# calculate the objective (multiplied by -1 because minimization is assumed)
out["F"] = - np.sin(x_as_int * np.pi / (2 ** n))
problem = MyProblem()
# initialize the genetic algorithm with binary operators
algorithm = GA(
pop_size=10,
sampling=get_sampling("bin_random"),
crossover=get_crossover("bin_ux"),
mutation=get_mutation("bin_bitflip"))
res = minimize(problem,
algorithm,
seed=1,
verbose=True)
print(res.X.astype(np.int))
print(- res.F)
输出:
[1 0 0 0 0 0 0 0]
[1.]
您还可以制定问题以直接优化离散值。
整型变量
import numpy as np
from pymoo.algorithms.so_genetic_algorithm import GA
from pymoo.factory import get_sampling, get_crossover, get_mutation
from pymoo.model.problem import Problem
from pymoo.optimize import minimize
class MyProblem(Problem):
def __init__(self):
super().__init__(n_var=1,
n_obj=1,
n_constr=0,
xl=0,
xu=256)
def _evaluate(self, x, out, *args, **kwargs):
out["F"] = - np.sin(x * np.pi / 256)
problem = MyProblem()
# initialize the genetic algorithm with binary operators
algorithm = GA(pop_size=15,
sampling=get_sampling("int_random"),
crossover=get_crossover("int_sbx", prob=1.0, eta=3.0),
mutation=get_mutation("int_pm", eta=3.0),
)
res = minimize(problem,
algorithm,
seed=1,
verbose=True)
print(res.X.astype(np.int))
print(- res.F)
在遗传算法中,变量表示是必不可少的,并且直接与所使用的进化算子一起出现。