基于遗传算法在二维空间物体的排布—python

实现需求

基于遗传算法在二维空间物体的排布,将随机的二维物体进行遗传进化最后得到想要的结果,代码程序中种群为100,迭代600次,每次迭代保留最好的50个种群,剩余50个种群进行交叉变异,下图为迭代的结果。

目标结果

根据matplotlib保存的图片可视化结果可以看出物体在向好的方向迭代

代码实现

干货!!!!!

import random
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import tqdm
random.seed(1024)
# 设置房间尺寸及设备尺寸
room_width = 12
room_height = 12
cabinet = (2, 2)  # 机柜尺寸(宽, 高)


def calculate_ac_count(cabinet_count):
    # 计算所需空调数量
    # return (cabinet_count + 3) // 4
    return 0


def generate_individual(cabinet_count, ac_count):
    """ 生成个体,确保横向排列且纵向间隔至少为1 """
    individual = []
    # 为空调和机柜分配位置
    for i in range(ac_count + cabinet_count):
        rotation = random.randint(0, 1)  # 0表示未旋转,1表示旋转
        # if i < ac_count:
        #     width, height = (air_conditioner[1], air_conditioner[0]) if rotation else air_conditioner
        # else:
        width, height = (cabinet[1], cabinet[0]) if rotation else cabinet

        x = random.randint(1, room_width - width)
        y = random.randint(1, room_height - height)
        individual.append([x, y, rotation])
        # print(x,y)
    return individual


def calculate_fitness(individual, cabinet_count, ac_count):
    """ 计算适应度,考虑横向不重叠且纵向间隔为1 """
    penalty = 200
    objects = individual[:ac_count] + individual[ac_count:]

    # 罚分规则
    for i in range(len(objects)):
        xi, yi, ri = objects[i]

        for j in range(i + 1, len(objects)):
            xj, yj, rj = objects[j]
            # 横向不重叠检查
            # horizontal_overlap = xi < xj + wj and xi + wi > xj
            horizontal_overlap = abs(xi - xj) < 3
            # 纵向间隔检查
            vertical_gap = (abs(yi - yj) < 3)

            if horizontal_overlap and vertical_gap:
                penalty += 500  # 重叠或纵向间隔不足
            if abs(xi - xj) == 3 and abs(yi - yj) == 3:
                penalty -= 50  # 重叠或纵向间隔不足
            # if (xi + xj + wj)<4 and yi -yj:
            #     penalty += 1000
    # print("penalty",penalty)
    return penalty

def crossover(ind1, ind2):
    """交叉函数"""
    point = random.randint(1, len(ind1) - 1)
    return ind1[:point] + ind2[point:], ind2[:point] + ind1[point:]


def mutate(individual, width, height):
    """变异函数"""
    index = random.randint(0, len(individual) - 1)
    individual[index] = [random.randint(1, width - 1), random.randint(1, height - 1), random.randint(0, 1)]
    return individual


def genetic_algorithm(cabinet_count):
    # ac_count = calculate_ac_count(cabinet_count)
    ac_count = 5
    population_size = 100
    population = [generate_individual(cabinet_count, 0) for _ in range(population_size)]
    # print("population",population)
    number_of_generations = 600
    # start_sorted_population = sorted(population)
    sorted_population = []

    for _ in tqdm.tqdm(range(1,number_of_generations+1)):
        # print(_)
        sorted_population = sorted(population, key=lambda x: calculate_fitness(x, cabinet_count, ac_count))
        # print("sorted_population",sorted_population)
        new_population = sorted_population[:50]  # 保留最好的一半
        while len(new_population) < population_size:
            parent1, parent2 = random.sample(new_population, 2)
            child1, child2 = crossover(parent1, parent2)
            new_population.append(mutate(child1, room_width - 1, room_height - 1))
            new_population.append(mutate(child2, room_width - 1, room_height - 1))
        population = new_population
        # print(population)
        if _%50 ==0:
            plot_layout(sorted_population[0], 0,epoch=_)
    return sorted_population[0]


def plot_layout(layout, ac_count,epoch):
    fig, ax = plt.subplots()
    ax.set_xlim(0, room_width)
    ax.set_ylim(0, room_height)
    colors = ['blue', 'green']

    for i, obj in enumerate(layout):
        color = colors[0] if i < ac_count else colors[1]
        width, height = cabinet
        if obj[2] == 1:  # 如果有旋转
            width, height = height, width
        rect = patches.Rectangle((obj[0], obj[1]), width, height, linewidth=1, edgecolor='black', facecolor=color,
                                 alpha=0.5)
        ax.add_patch(rect)
    plt.title("epoch = {}".format(epoch))
    plt.savefig('figures/{}.png'.format(epoch))
    # plt.show()


import time
# 输入机柜数量
cabinet_count = int(input("请输入机柜数量: "))
start = time.time()
best_layout = genetic_algorithm(cabinet_count)
ac_count = calculate_ac_count(cabinet_count)
print(time.time()-start)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值