遗传算法求解旅行商问题(含python源代码)

news2024/11/18 15:38:39

目录

前言

编码初始化种群

计算适应度

选择

交叉

变异

完整代码

总结


前言

这次的算法有一点不能确定是否正确,希望有大佬能够批评指正。

遗传算法的一般步骤

编码初始化种群

种群(population)指同一时间生活在一定自然区域内,同种生物的所有个体。

所以种群是由个体组成的,所以先需要得到个体,然后再随机产生一定数目的个体。

在本算法中个体采用的是实数编码

先对城市的位置进行初始化,采用的是用列表来表示城市的坐标,可以单个定义,也可以随机生成。

先生成一串有序的数字用来表示城市的编号,再每次随机进行打乱后储存到pop列表中,pop表示种群,里面装着的是列表用来表示个体。(个体表示城市的编号,种群表示编号打乱后个体的集合)

群体规模太小,不能提供足够的采样点,以致算法性能很差,易陷入局部最优解。

群体规模太大,尽管可以增加优化信息,阻止早熟收敛的发生,但无疑会增加计算量,造成收敛时间太长,表现为收敛速度缓慢。

City_Map = 100 * np.random.rand(20, 2)  # 随机产生20个城市(20行2列,数值乘以100)
DNA_SIZE = len(City_Map)  # 编码长度(返回行的个数)
POP_SIZE = 100  # 种群大小
# 生成初代种群pop
pop = []
list = list(range(DNA_SIZE))  # 生成[0,DNA_SIZE)的列表
for i in range(POP_SIZE):  # POP_SIZE是指种群大小,在程序中是一个固定的值(打乱POP_SIZE次之后把结果储存到pop列表中
    random.shuffle(list)  # 随机打乱list,进行初始化操作
    l = list.copy()  # 把list中的数据拷贝到l中
    pop.append(l)  # 将l添加到pop列表中

计算适应度

适应度函数值只能是正值,越大越好。

DNA表示个体,根据个体的值(表示城市的编号)来计算距离。

旅行商问题要求距离越短越好,所以距离越大越不满足要求,故而可以通过对距离求倒数来表示适应度。

在最后减去适应度最小的值,可以保证适应度都为正值。(如果有负数,减去一个更小的负数,会变成正值)

def distance(DNA):  # 根据DNA的路线计算距离
    dis = 0
    temp = City_Map[DNA[0]]
    for i in DNA[1:]:
        # sqrt(pow(x-x0,2)+pow(y-y0,2))
        dis = dis + ((City_Map[i][0] - temp[0]) ** 2 + (City_Map[i][1] - temp[1]) ** 2) ** 0.5
        temp = City_Map[i]
    return dis + ((temp[0] - City_Map[DNA[0]][0]) ** 2 + (temp[1] - City_Map[DNA[0]][1]) ** 2) ** 0.5


def getfitness(pop):  # 计算种群适应度,这里适应度用距离的倒数表示
    temp = []
    for i in range(len(pop)):
        temp.append(1 / (distance(pop[i])))
    # 减去最小值是为了防止适应度出现负值
    return temp - np.min(temp)

选择

选择操作也称为复制( reproduction) 操作:从当前群体中按照一定概率选出优良的个体, 使它们有机会作为父代繁殖下一代子孙。
判断个体优良与否的准则是各个个体的适应度值:个体适应度越高, 其被选择的机会就越多。

在程序中个体的选择方法采用的是轮盘赌的方法:

按个体的选择概率产生一个轮盘,轮盘每个区的角度与个体的选择概率成比例。
产生一个随机数, 它落入转盘的哪个区域就选择相应的个体交叉
适应度的小的个体也有可能被选中。

def select(pop, fitness):  # 根据适应度选择,以赌轮盘的形式,适应度越大的个体被选中的概率越大
    # print(fitness)
    s = fitness.sum()
    # np.random.choice(a,size,replace,p=None)随机抽取样本a,表示范围,replace=True被抽中后仍有机会被再次抽中,p没抽中的概率
    temp = np.random.choice(np.arange(len(pop)), size=POP_SIZE, replace=True, p=(fitness / s))
    p = []
    for i in temp:
        p.append(pop[i])

    return p

交叉

程序中交叉采用部分匹配交叉,如果直接采用两点交叉会导致一个个体中出现两个重复的城市。

部分匹配交叉保证了每个染色体中的基因仅出现一次,通过该交叉策略在一个染色体中不会出现重复的基因,所以部分匹配交叉经常用于旅行商(TSP)或其他排序问题编码。部分匹配交叉类似于两点交叉,通过随机选择两个交叉点确定交叉区域。执行交叉后一般会得到两个无效的染色体,个别基因会出现重复的情况,为了修复染色体,可以在交叉区域内建立每个染色体的匹配关系,然后在交叉区域外对重复基因应用此匹配关系就可以消除冲突。

交叉概率太大时,种群中个体更新很快,会造成高适应度值的个体很快被破坏掉;

概率太小时,交叉操作很少进行,从而会使搜索停滞不前,造成算法的不收敛。

def crossmuta(pop, CROSS_RATE):  # 交叉变异
    new_pop = []
    for i in range(len(pop)):  # 遍历种群中的每一个个体,将该个体作为父代
        n = np.random.rand()
        if n >= CROSS_RATE:  # 大于交叉概率时不发生变异,该子代直接进入下一代
            temp = pop[i].copy()
            new_pop.append(temp)  # 直接进行拷贝

        if n < CROSS_RATE:  # 小于交叉概率时发生变异
            list1 = pop[i].copy()
            list2 = pop[np.random.randint(POP_SIZE)].copy()  # 选取种群中另一个个体进行交叉(随机选择)
            status = True
            while status:  # 产生2个不相等的节点,中间部分作为交叉段,采用部分匹配交叉(直到k1<k2的时候才会跳出循环)
                k1 = random.randint(0, len(list1) - 1)
                k2 = random.randint(0, len(list2) - 1)
                if k1 < k2:
                    status = False

            k11 = k1  # 保存切片起始的下标

            # 先对部分片段进行切片,把切片出来的内容进行交换(完全交换)
            fragment1 = list1[k1: k2]
            fragment2 = list2[k1: k2]

            list1[k1: k2] = fragment2
            list2[k1: k2] = fragment1

            del list1[k1: k2]  # 删除list1中[k1,k2)的内容
            left1 = list1

            # 进行部分匹配的交叉
            offspring1 = []#后代
            #对left1中的每一个位置pos遍历
            for pos in left1:
                #检查它是否存在于frag2中
                if pos in fragment2:
                    #从fragment1中找到对应的基因
                    pos = fragment1[fragment2.index(pos)]
                    #直到基因不再fragment2中为止(遍历fragment2,确保每一个基因都和pos不同)
                    while pos in fragment2:
                        pos = fragment1[fragment2.index(pos)]
                    offspring1.append(pos)
                    continue
                #如何pos不存在fragment2中,那么就直接将其添加到新的后代中
                offspring1.append(pos)
            # 插入新片段
            for i in range(0, len(fragment2)):
                offspring1.insert(k11, fragment2[i])
                k11 += 1
            temp = offspring1.copy()

            mutation(temp, MUTA_RATE)  # 进行变异

            new_pop.append(temp)  # 把部分匹配交叉后形成的合法个体加入到下一代种群

    return new_pop

变异

互换变异:随机选取染色体的两个基因进行简单互换。
采用随机的形式,在[0,DNA_SIZE)的范围内生成两个下标(确保两个位置不一致),在将两个位置上面的值进行交换。

变异概率太小则很难产生新模式,变异概率太大则会使遗传算法成为随机搜索算法。

def mutation(DNA, MUTA_RATE):  # 进行变异
    # 两点变异
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率进行变异
        mutate_point1 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因的位置
        mutate_point2 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因的位置
        while (mutate_point1 == mutate_point2):  # 保证2个所选位置不相等
            mutate_point2 = np.random.randint(0, DNA_SIZE)  #如果相等将mutate_point2重新进行随机生成位置
        DNA[mutate_point1], DNA[mutate_point2] = DNA[mutate_point2], DNA[mutate_point1]  # 2个所选位置进行互换

逆转变异:在个体码串中随机选择两点( 逆转点) ,然后将两点之间的基因值以逆向排序插入到原位置中。

随机生成两个下标,如x1,x2(确保x1<x2),对列表进行[x1,x2)的切片,在原始的列表中删除切片的部分,将切片的部分翻转之后添加到原始的位置。

def mutation(DNA, MUTA_RATE):  # 进行变异
    # 逆转变异
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率进行变异
        status = True
        while status:  # 产生2个不相等的节点,中间部分作为交叉段,采用部分匹配交叉(直到mutate_point1<mutate_point2的时候才会跳出循环)
            mutate_point1 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因片段的起始的位置
            mutate_point2 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因片段的结束的位置
            if mutate_point1 < mutate_point2:
                status = False

        k1 = mutate_point1  # 保存切片起始的下标
        temp = DNA[mutate_point1:mutate_point2]  # 把需要逆转的片段先提取出来
        del DNA[mutate_point1:mutate_point2]  # 先暂时删除这段片段
        temp.reverse()  # 反转基因序列
        # 插入翻转后的新片段
        for i in range(0, len(temp)):
            DNA.insert(k1, temp[i])
            k1 += 1

插入变异:在个体码串中随机选择一个码, 然后将此码插入随机选择的插入点中间。

随机生成两个实数,这次不是交换,是插入的方式,也就是插入点之后的元素的位置都会发生改变。

def mutation(DNA, MUTA_RATE):  # 进行变异
    #插入变异
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率进行变异
        mutate_point1 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因的位置(选中一个基因)
        mutate_point2 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因的位置(插入点)
        while (mutate_point1 == mutate_point2):  # 保证2个所选位置不相等
            mutate_point2 = np.random.randint(0, DNA_SIZE)

        temp=DNA[mutate_point1]#先保存mutate_point1对应的值
        del DNA[mutate_point1]#删除mutate_point1对应的值
        DNA.insert(mutate_point2,temp)#重新插入到列表中

完整代码

import time
import numpy as np
import random
import matplotlib.pyplot as plt

# 各个城市的坐标
City_Map = 100 * np.random.rand(10, 2)  # 随机产生20个城市(20行2列,数值乘以100)

DNA_SIZE = len(City_Map)  # 编码长度(返回行的个数)
POP_SIZE = 100  # 种群大小
CROSS_RATE = 0.85  # 交叉率
MUTA_RATE = 0.15  # 变异率
Iterations = 500  # 迭代次数


def distance(DNA):  # 根据DNA的路线计算距离
    dis = 0
    temp = City_Map[DNA[0]]
    for i in DNA[1:]:
        # sqrt(pow(x-x0,2)+pow(y-y0,2))
        dis = dis + ((City_Map[i][0] - temp[0]) ** 2 + (City_Map[i][1] - temp[1]) ** 2) ** 0.5
        temp = City_Map[i]
    return dis + ((temp[0] - City_Map[DNA[0]][0]) ** 2 + (temp[1] - City_Map[DNA[0]][1]) ** 2) ** 0.5


def getfitness(pop):  # 计算种群适应度,这里适应度用距离的倒数表示
    temp = []
    for i in range(len(pop)):
        temp.append(1 / (distance(pop[i])))
    # 减去最小值是为了防止适应度出现负值
    return temp - np.min(temp)


def select(pop, fitness):  # 根据适应度选择,以赌轮盘的形式,适应度越大的个体被选中的概率越大
    # print(fitness)
    s = fitness.sum()
    # np.random.choice(a,size,replace,p=None)随机抽取样本a,表示范围,replace=True被抽中后仍有机会被再次抽中,p没抽中的概率
    temp = np.random.choice(np.arange(len(pop)), size=POP_SIZE, replace=True, p=(fitness / s))
    p = []
    for i in temp:
        p.append(pop[i])

    return p


def mutation(DNA, MUTA_RATE):  # 进行变异
    # 两点变异
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率进行变异
        mutate_point1 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因的位置
        mutate_point2 = np.random.randint(0, DNA_SIZE)  # 随机产生一个实数,代表要变异基因的位置
        while (mutate_point1 == mutate_point2):  # 保证2个所选位置不相等
            mutate_point2 = np.random.randint(0, DNA_SIZE)  #如果相等将mutate_point2重新进行随机生成位置
        DNA[mutate_point1], DNA[mutate_point2] = DNA[mutate_point2], DNA[mutate_point1]  # 2个所选位置进行互换
    

def crossmuta(pop, CROSS_RATE):  # 交叉变异
    new_pop = []
    for i in range(len(pop)):  # 遍历种群中的每一个个体,将该个体作为父代
        n = np.random.rand()
        if n >= CROSS_RATE:  # 大于交叉概率时不发生变异,该子代直接进入下一代
            temp = pop[i].copy()
            new_pop.append(temp)  # 直接进行拷贝

        if n < CROSS_RATE:  # 小于交叉概率时发生变异
            list1 = pop[i].copy()
            list2 = pop[np.random.randint(POP_SIZE)].copy()  # 选取种群中另一个个体进行交叉(随机选择)
            status = True
            while status:  # 产生2个不相等的节点,中间部分作为交叉段,采用部分匹配交叉(直到k1<k2的时候才会跳出循环)
                k1 = random.randint(0, len(list1) - 1)
                k2 = random.randint(0, len(list2) - 1)
                if k1 < k2:
                    status = False

            k11 = k1  # 保存切片起始的下标

            # 先对部分片段进行切片,把切片出来的内容进行交换(完全交换)
            fragment1 = list1[k1: k2]
            fragment2 = list2[k1: k2]

            list1[k1: k2] = fragment2
            list2[k1: k2] = fragment1

            del list1[k1: k2]  # 删除list1中[k1,k2)的内容
            left1 = list1

            # 进行部分匹配的交叉
            offspring1 = []#后代
            #对left1中的每一个位置pos遍历
            for pos in left1:
                #检查它是否存在于frag2中
                if pos in fragment2:
                    #从fragment1中找到对应的基因
                    pos = fragment1[fragment2.index(pos)]
                    #直到基因不再fragment2中为止(遍历fragment2,确保每一个基因都和pos不同)
                    while pos in fragment2:
                        pos = fragment1[fragment2.index(pos)]
                    offspring1.append(pos)
                    continue
                #如何pos不存在fragment2中,那么就直接将其添加到新的后代中
                offspring1.append(pos)
            # 插入新片段
            for i in range(0, len(fragment2)):
                offspring1.insert(k11, fragment2[i])
                k11 += 1
            temp = offspring1.copy()

            mutation(temp, MUTA_RATE)  # 进行变异

            new_pop.append(temp)  # 把部分匹配交叉后形成的合法个体加入到下一代种群

    return new_pop


def print_info(pop):  # 用于输出结果
    fitness = getfitness(pop)
    maxfitness = np.argmax(fitness)  # 得到种群中最大适应度个体的索引
    # 打印结果
    print("最优的基因型:", pop[maxfitness])
    print("最短距离:", distance(pop[maxfitness]))
    # 按最优结果顺序把地图上的点加入到best_map列表中
    best_map = []
    for i in pop[maxfitness]:
        best_map.append(City_Map[i])
    best_map.append(City_Map[pop[maxfitness][0]])
    X = np.array((best_map))[:, 0]
    Y = np.array((best_map))[:, 1]
    # 绘制地图以及路线
    plt.figure()
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.scatter(X, Y)
    for dot in range(len(X) - 1):
        plt.annotate(pop[maxfitness][dot], xy=(X[dot], Y[dot]), xytext=(X[dot], Y[dot]))
    plt.annotate('start', xy=(X[0], Y[0]), xytext=(X[0] + 1, Y[0]))
    plt.plot(X, Y)


if __name__ == "__main__":  # 主循环
    # 生成初代种群pop
    pop = []
    list = list(range(DNA_SIZE))  # 生成[0,DNA_SIZE)的列表
    for i in range(POP_SIZE):  # POP_SIZE是指种群大小,在程序中是一个固定的值(打乱POP_SIZE次之后把结果储存到pop列表中
        random.shuffle(list)  # 随机打乱list,进行初始化操作
        l = list.copy()  # 把list中的数据拷贝到l中
        pop.append(l)  # 将l添加到pop列表中
    best_dis = []
    # 最好适应度
    #goodFitness = 0
    # 最差适应度(如果进行归一化处理之后,适应度都减去最小值,那么他的最差适应度不都就是0了)
    #chaFitness = 0
    # 总体适应度
    #sumFitness = 0
    # 所有数量
    #sumCount = 0
    # 平均适应度
    #averageFitness = 0

    # 获取当前时间(算法开始时间)
    start_time = time.time()

    # 进行选择,交叉,变异,并把每代的最优个体保存在best_dis中
    for i in range(Iterations):  # 迭代N代
        pop = crossmuta(pop, CROSS_RATE)  # CROSS_RATE交叉率
        fitness = getfitness(pop)  # 得到适应度种群的适应度
        # 更新最差适应度
        # print(np.min(fitness))
        tmpfitness = np.max(fitness)

        # 更新最好适应度
        #if tmpfitness > goodFitness:
        #    goodFitness = tmpfitness
        # print(goodFitness)

        # 记录所有适应度的值
        #sumFitness = np.sum(fitness) + sumFitness
        # 记录所有适应度的个数
        #sumCount = sumCount + np.size(fitness)

        maxfitness = np.argmax(fitness)  # 返回数值最大的索引
        best_dis.append(distance(pop[maxfitness]))
        pop = select(pop, fitness)  # 选择生成新的种群(适应度最大的)
        print("iteration", i)

    #averageFitness = sumFitness / sumCount
    # 获取当前时间(算法结束时间)
    end_time = time.time()

    print_info(pop)  # 打印信息

    print('逐代的最小距离:', best_dis)
    #print(f'最好适应度:{goodFitness:.4f}')
    #print(f'最差适应度:{chaFitness:.4f}')
    #print(f'平均适应度:{averageFitness:.4f}')
    print(f'程序运行时间:{(end_time - start_time):.4f}秒')
    #print(pop)


# 画图
plt.figure()
plt.plot(range(Iterations), best_dis)
plt.show()
plt.close()

参考信息

遗传算法入门详解 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/100337680遗传算法python进阶理解+论文复现(纯干货,附前人总结引路)_python神经网络遗传算法_不想秃头的夜猫子的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/golden_knife/article/details/128510731通俗易懂地解释遗传算法 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/136393730遗传算法解决旅行商问题(详细解释+代码分享) - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/344588977用遗传算法求解旅行商问题_中国旅行商问题,34个省会-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/breeze_blows/article/details/102992997遗传算法(三)——适应度与选择_遗传算法适应度函数-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_30239361/article/details/101540896

总结

这个最好适应度,最差适应度以及平均适应度的概念没完全掌握,不知道是不是这一个意思,所以在程序中注释了,大家可以根据自己的理解来添加。

遗传算法的思路是“适者生存,优胜劣汰”,模拟生物的进化,以一个初始生物群体为起点,经过竞争后,一部分个体被淘汰而无法再进入这个循环圈,而另一部分则胜出成为种群。对于算法的选择的个体,适应度高的并不一定进入种群,只是进入种群的可能性比较大;而适应度低的个体并不一定被淘汰,只是进入种群的可能性比较小,这个也是与生物进化论相挂钩的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1118270.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

推荐3个好评如潮的多人协作软件!

​在当今高度互联的社会中&#xff0c;多人协作已成为团队高效工作的关键。为了更好地满足团队合作的需求&#xff0c;许多优秀的多人协作软件应运而生。 在本文中&#xff0c;我们将向大家推荐3款拥有良好口碑的多人协作软件&#xff1a;boardmix博思白板、Notion和Trello。这…

Linux_API_系列-整体概览

总论 Linux下API编程不像Windows一样&#xff0c;对每种设备和不同功能都有统一的API&#xff0c;所以有了《Windows核心编程》这种导论一类的大而全的书籍&#xff0c;整本书厚的像一块砖头。 Linux下贯彻了一贯的“一切皆文件”的宗旨&#xff0c;所以对于系统编程而言&…

Linux进程概念(下)

僵尸进程 进程内核数据结构PCB进程的代码和数据&#xff0c;都要占据内存空间&#xff0c;那么进程退出的核心工作之一&#xff1a;即将PCB和自己的代码和数据释放掉 我们创建进程的目标一定是为了完成某种任务&#xff0c;父进程/OS要知道该进程把任务完成的怎么样&#xff…

轻松实现批量转换,将JPG图片一键转换为PNG格式!

在处理大量图片时&#xff0c;将JPG格式图片转换为PNG格式可能会耗费您大量的时间和精力。为了让您的工作更加轻松&#xff0c;我们为您推出了一款高效的批量图片处理工具&#xff0c;让您能够轻松将JPG图片一键转换为PNG格式&#xff0c;提高处理效率&#xff01; 首先&#…

使用命令行cli脚手架创建uniapp项目(微信小程序、H5、APP)

除了使用HBuilderX工具可视化搭建项目外&#xff0c;DCloud官方还提供了一个脚手架用于命令行搭建项目。 uni-app项目支持 uni cli和 HBuilderX cli两种脚手架工具&#xff1a; uni cli&#xff1a;面向非HBuilderX的用户&#xff08;如习惯使用vscode/webstorm的开发者&#…

【数据结构】八大排序

目录 1. 排序的概念及其作用 1.1 排序的概念 1.2 排序运用 1.3 常见的排序算法 2. 常见排序算法的实现 2.1 插入排序 2.1.1 基本思想 2.1.2 直接插入排序 2.1.3 希尔排序&#xff08;缩小增量排序&#xff09; 2.2 选择排序 2.2.1 基本思想 2.2.2 直接选择排序 2.2…

掌握Java中的volatile关键字

高速缓存 什么是高速缓存 高速缓存&#xff08;Cache&#xff09;是一种用于存储计算机数据的临时存储设备&#xff0c;用于加速数据访问速度&#xff0c;减少对主存储器&#xff08;RAM&#xff09;或磁盘的频繁访问。高速缓存通过将最常用的数据存储在更接近CPU的位置&…

使用Perl和WWW::Mechanize库编写

以下是一个使用Perl和WWW::Mechanize库编写的网络爬虫程序的内容。代码必须使用以下代码&#xff1a;jshk.com.cn/get_proxy 首先&#xff0c;确保已经安装了Perl和WWW::Mechanize库。如果没有&#xff0c;请使用以下命令安装&#xff1a; cpan WWW::Mechanize创建一个新的Pe…

【MATLAB源码-第52期】基于matlab的4用户DS-CDMA误码率仿真,对比不同信道以及不同扩频码。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. DS-CDMA系统 DS-CDMA (Direct Sequence Code Division Multiple Access) 是一种多址接入技术&#xff0c;其基本思想是使用伪随机码序列来调制发送信号。DS-CDMA的特点是所有用户在同一频率上同时发送和接收信息&#xf…

抖音热搜榜:探索热门话题的独特魅力

在信息爆炸的时代&#xff0c;我们每天都会接收到大量的信息&#xff0c;而抖音热搜榜就像是一个窗口&#xff0c;让我们能够窥见当下最受欢迎、最具话题性的内容。作为全球最受欢迎的短视频平台之一&#xff0c;抖音凭借其海量的内容、独特的推荐算法&#xff0c;让越来越多的…

阿里低代码Low Code Engine快速上手

一、环境准备 在正式开始之前,我们需要先安装相应的软件:WSL、Node等。Window 环境需要使用 WSL 在 windows 下进行低代码引擎相关的开发。安装教程➡️ WSL 安装教程。对于 Window 环境来说,之后所有需要执行命令的操作都是在 WSL 终端执行的。 2.1 Node 推荐安装Node 1…

Topaz Photo AI forMac/win:革命性的图片降噪软件

Topaz Photo AI是一款革命性的图片降噪软件&#xff0c;它利用人工智能技术对图片进行降噪处理&#xff0c;让你的照片焕然一新。与传统的降噪软件不同&#xff0c;Topaz Photo AI不仅降噪效果更出色&#xff0c;而且操作简单&#xff0c;让你可以轻松地提升图片质量。 Topaz …

CUDA学习笔记6——事件计时

事件计时 CUDA事件是直接在GPU上实现的&#xff0c;因此它们不适用于对同时包含设备代码和主机代码的混合代码计时。 cudaEventCreate 创建一个事件cudaEventRecord 记录一个事件cudaEventElapsedTime 计算两个事件之间经历的时间&#xff0c;第一个参数为某个浮点变量的地址…

MS12_020 3389远程溢出漏洞

1.search ms12_020 搜索ms12_020 2.use auxiliary/scanner/rdp/ms12_020_check 检查是否存在ms12_020漏洞 show options 查看所需参数 set RHOSTS x.x.x.x 设置目标IP地址 run 执行 检测出来有Ms12_020漏洞 3.use auxiliary/dos/windows/rdp/ms12_020_maxchannelids 选择…

SMOS土壤水分产品下载

SMOS土壤水分产品下载 打开下载网站 打开网站 打开DATA下的SMOS 然后找到SMOS的L1和L2data 首先需要注册一下&#xff0c;在该网站 然后找到了SMOS的NRT土壤水分产品&#xff0c;该产品从2010年开始&#xff0c;一直发布到现在&#xff0c;是基于L波段。 这里就是每天的土…

卷积神经网络CNN学习笔记-MaxPool2D函数解析

目录 1.函数签名:2.学习中的疑问3.代码 1.函数签名: torch.nn.MaxPool2d(kernel_size, strideNone, padding0, dilation1, return_indicesFalse, ceil_modeFalse) 2.学习中的疑问 Q:使用MaxPool2D池化时,当卷积核移动到某位置,该卷积核覆盖区域超过了输入尺寸时,MaxPool2D会…

emqx 启动正常,但是1883端口无法telnet,emqx无法正常工作

emqx一直正常工作&#xff0c;后面突然就不工作了&#xff0c;查找日志&#xff0c;发现报错说设备空间不足&#xff0c;但是我记得华为云SSD从40G扩容到500G&#xff0c;不至于空间不足&#xff0c;于是运行df -Dh确实显示只有40G&#xff0c;运行lsblk确实有500G&#xff0c;…

2016-2023全国MPA国家A类线趋势图:浙大MPA要高多少?

公共管理硕士&#xff08;MPA&#xff09;项目的国家线这些年相对比较平稳&#xff0c;虽然以体制内考生为主的项目总体应试能力是比较强的&#xff0c;但因为全国mpa项目众多&#xff0c;能力参差不齐&#xff0c;导致每年的国家线划定也需要考虑综合情况。根据专注浙大的杭州…

Qt实现一个电子相册

一、要实现的功能 在窗口中可以显示图片&#xff0c;并且能够通过两个按钮进行图片的前进和后退的顺序切换。有一个按钮&#xff0c;通过这个按钮可以从所存图片资源中随机选取一个图片进行展示通过按钮可以控制图片自动轮播顺序切换的开始与停止&#xff0c;显示当前系统的时…