DEAP:针对机票问题实施NSGA-ii

时间:2019-06-26 16:46:35

标签: python evolutionary-algorithm deap

我有一个列表,其中包含2个属性,分别是 cost rating 。我需要找到成本更低,评分更高的最佳航班。这是一个具有最小化和最大化目标的多对象优化问题。我该如何在DEAP中实现呢?

自从我对DEAP陌生以来,我一直在努力实现个人化。

# Attribute generator
toolbox.register("cost", random.randrange, NBR_ITEMS)
toolbox.register("rating", random.randrange, NBR_ITEMS)

# Structure initializers
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.cost, toolbox.rating) #
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

1 个答案:

答案 0 :(得分:1)

也许您可以尝试使用二进制数字对费用和等级进行编码。

例如,假设您能获得的最昂贵的机票是$ 16384,您可以将其存储在14位(2 ^ 14 = 16384)中,并且等级是0到10之间的数字,因此可以将其存储在4中位,因此总共可以使用18位存储您的个人。

现在您需要一个函数对其进行解码:

def decode_individual(individual):
    decoded_individual = ['', '']

    # Decode cost (14 bits)
    for i in range(0, 14):
        decoded_individual[0] += str(individual[i])

    # Decode rating (4 bits)
    for i in range(1, 3):
        decoded_individual[0] += str(individual[13 + i])

    return tuple(map(lambda x: int(x, 2), decoded_individual))

您需要为多目标问题设置适应度函数,即,您需要为每个函数提供一些权重,如果您要最大化该函数,则要为负数;如果要最小化该函数,则要为负数。对于您的情况,我想您正在尝试最大程度地降低评级并最小化成本,因此可以按以下步骤进行设置:

creator.create('Fitness', base.Fitness, weights=(1.0, -0.5,))
creator.create('Individual', list, fitness=creator.Fitness)

您的适应度方法应按权重指定的顺序返回您尝试最大化和最小化函数的结果:

def function_cost(individual):
    decoded_individual = decode_individual(individual)
    return decoded_individual[0]

def function_rating(individual):
    decoded_individual = decode_individual(individual)
    return decoded_individual[1]

def fitness(individual):
    return (function_cost(individual), function_rating(individual)),

然后,不要像您的示例那样注册2个健身功能,而只需注册一个:

toolbox.register('evaluate', fitness)

配置DEAP以使用二进制数据:

toolbox.register('attrBinary', random.randint, 0, 1)
toolbox.register('individual', tools.initRepeat, creator.Individual, toolbox.attrBinary, n=18) # Here you need to specify the number of bits you are using
toolbox.register('population', tools.initRepeat, list, toolbox.individual)

# Register the evaluation function (was named fitness in this example)
toolbox.register('evaluate', fitness)

# Configure your mate and mutation methods, e.g.
toolbox.register('mate', tools.cxTwoPoint)
toolbox.register('mutate', tools.mutFlipBit, indpb=0.15)

您的选择方法必须支持多目标问题,可以使用问题中指出的NSGA2

toolbox.register('select', tools.selNSGA2)

然后运行算法,您可以尝试使用不同的值来表示个体数(种群),世代数以及交配和突变的等级:

num_pop = 50
num_gen = 100
cx_prob = 0.7
mut_prob = 0.2

best = []

for gen in range(num_gen):
    offspring = algorithms.varAnd(population, toolbox, cxpb=cx_prob, mutpb=mut_prob)
    fits = toolbox.map(toolbox.evaluate, offspring)

    for fit, ind in zip(fits, offspring):
        ind.fitness.values = fit

    population = toolbox.select(offspring, k=len(population))
    top = tools.selBest(population, k=1)
    fitness = fitness(top[0])

    print(gen, fitness, decode_individual(top[0]), top[0])
    best.append(fitness[0])

您可能还想在图表中显示每一代的最佳个人:

x = list(range(num_gen))
plt.plot(x, best)
plt.title("Best ticket - Cost / Rating")
plt.show()

我自己还没有测试过,我从大学里做过的一些运动中获得了很大的启发,希望它对您有用。