粒子群算法求解0-1背包问题的python实现

具体算法原理评论区提问吧,或者有时间的话我再写原理部分
代码自己手写的,有详细注释
import numpy as np
import random
import math
import matplotlib.pyplot as plt
from time import *


def init_x(n, d):
    """
    :param n: 粒子总数量
    :param d: 粒子种基因个数(维度)
    :return: 随机生成的种群(二维list)
    """
    population = []
    for i in range(n):
        gene = []
        for j in range(d):
            a = np.random.randint(0, 2)
            gene.append(a)
        population.append(gene)
    return population


def init_v(n, d, V_max, V_min):
    """
    :param n: 粒子总数量
    :param d: 粒子种基因个数(维度)
    :return: 随机生成的种群(二维list)
    """
    v = []
    for i in range (n):
        vi = []
        for j in range (d):
            a = random.random() * (V_max - V_min) + V_min
            vi.append(a)
        v.append(vi)
    return v


def fitness(p, n, d, w, w_max, v, afa):
    """
    :param p: 粒子群
    :param n: 群体粒子个数
    :param d: 粒子维数
    :param w: 物品的重量列表
    :param w_max: 背包最大容量
    :param v: 物品的价值列表
    :param afa: 惩罚系数
    :return: pbest每一个粒子的适应度列表
    :return: fitweight每一个粒子的重量
    tips: 如果物品总重量大于背包最大容量时,引入惩罚系数
    """
    fitvalue = []
    fitweight = []
    for i in range (n):
        a = 0  # 每个粒子的重量
        b = 0  # 每个粒子的价值(适应度)
        for j in range(d):
            if p[i][j] == 1:
                a += w[j]
                b += v[j]
        if a > w_max:
            b = 0
            # b = b + afa * (w_max - a)  # 超重
        fitvalue.append(b)
        fitweight.append(a)
    return fitvalue, fitweight


def update_pbest(p, fitvalue, pbest, px, m):
    """
    更新个体最优
    :param p: 当前种群
    :param fitvalue: 当前每个粒子的适应度
    :param pbest: 更新前的个体最优
    :param px: 更新前的个体最优解
    :param m: 粒子数量
    :return: 更新后的个体最优值、个体最优解
    """
    pb = pbest
    for i in range (m):
        if fitvalue[i] > pbest[i]:
            pbest[i] = fitvalue[i]
            px[i] = p[i]
    return pb, px


def update_gbest (p, pbest, gbest, g, m):
    """
    更新全局最优解
    :param p: 粒子群
    :param pbest: 个体适应度(个体最优)
    :param gbest: 全局最优
    :param g: 全局最优解
    :param m: 粒子数量
    :return: gbest全局最优,g对应的全局最优解
    """
    gb=gbest
    for i in range (m):
        if pbest[i] > gb:
            gb = pbest[i]
            g = p[i]
    return gb, g


def update_v(v, x, m, n, pbest, g, c1, c2, vmax, vmin):
    """
    更新速度
    :param v:更新前的速度
    :param x: 更新前的位置
    :param m: 粒子数量
    :param n: 粒子维度
    :param pbest: 个体最优解(二维列表)
    :param g: 全局最优解(一维列表)
    :param c1: 加速因子
    :param c2: 加速因子
    :param vmax: 最大速度
    :param vmin: 最小速度
    :return: 更新后的速度二维列表
    """
    for i in range (m):
        a = random.random()
        b = random.random()
        for j in range (n):
            v[i][j]=v[i][j]+c1*a*(pbest[i][j]-x[i][j]) + c2*b*(g[j]-x[i][j])
            if v[i][j] < vmin:
                v[i][j] = vmin
            if v[i][j] > vmax:
                v[i][j] = vmax
    return v


def update_x(x, v, m, n):
    """
    更新x
    :param x:更新前的x
    :param v: 更新后的v
    :param m: 粒子数量
    :param n: 粒子维度
    :return: 更新后的x
    """
    for i in range (m):
        for j in range(n):
            a = random.random()
            x[i][j] = 1/(1+math.exp(-v[i][j]))
            if x[i][j] > a:
                x[i][j] = 1
            else:
                x[i][j] = 0
    return x


# main()
if __name__ == '__main__':
	begin_time = time()
	Weight = [95,75,23,73,50,22,6,57,89,98]  # 物品体积
	Value = [89,59,19,43,100,72,44,16,7,64]  # 物品价值
	N = 100  # 群体粒子个数
	D = len(Weight)  # 粒子维数
	T = 100  # 最大迭代次数
	c1 = 1.5  # 学习因子1
	c2 = 1.5  # 学习因子2
	W_max = 0.8  # 惯性权重最大值
	W_min = 0.4  # 惯性权重最小值
	V_max = 10  # 速度最大值
	V_min = -10  # 速度最小值
	Weight_max = 300  # 背包容量
	
	afa = 10  # 惩罚系数
	item = []  # 用于记录每一次迭代的全局最优值
	itemg = []  # 用于记录每一次迭代的全局最优解
	x = init_x(N, D)  # 初始化x
	v = init_v(N, D, V_max, V_min)  # 初始化v
	fv, fw = fitness(x, N, D, Weight, Weight_max, Value, afa)  # 计算第一次迭代的适应度
	pb, px = fv, x  # 由于是第一次迭代,个体最优为当前值
	gb, g = update_gbest(x, pb, 0, [], N)  # 同理,寻找第一代的全局最优
	item.append(gb)  # item列表记录每一次迭代的全局最优
	itemg.append(g)
	v = update_v(v, x, N, D, px, g, c1, c2, V_max, V_min)  # 更新下一代的速度
	x = update_x(x, v, N, D)  # 更新下一代的位置
	
	for i in range(T):
	    fv, fw = fitness(x, N, D, Weight, Weight_max, Value, afa)
	    pb, px = update_pbest(x, fv, pb, px, N)
	    gb, g = update_gbest(x, pb, gb, g, N)
	    item.append(gb)
	    itemg.append(g)
	    v = update_v(v, x, N, D, px, g, c1, c2, V_max, V_min)
	    x = update_x(x, v, N, D)
	
	print(gb)
	plt.plot(item)
	plt.show()
	end_time = time()
	run_time = end_time - begin_time
	print('粒子群算法计算时间为:', run_time)
  • 14
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
下面是使用粒子算法求解01背包问题Python代码: ```python import random # 01背包问题 class KnapsackProblem: def __init__(self, n, c, w, v): self.n = n # 物品数量 self.c = c # 背包容量 self.w = w # 物品重量 self.v = v # 物品价值 # 计算个体的适应度 def fitness(self, x): weight = sum([x[i] * self.w[i] for i in range(self.n)]) # 计算重量 if weight > self.c: # 如果超过了背包容量,则适应度为0 return 0 else: # 否则适应度为物品的总价值 return sum([x[i] * self.v[i] for i in range(self.n)]) # 粒子算法 class PSO: def __init__(self, problem, pop_size, max_iter, c1, c2, w): self.problem = problem # 问题实例 self.pop_size = pop_size # 粒子群大小 self.max_iter = max_iter # 最大迭代次数 self.c1 = c1 # 学习因子1 self.c2 = c2 # 学习因子2 self.w = w # 惯性因子 self.gbest = None # 全局最优解 self.particles = [] # 所有粒子 self.init_particles() # 初始化所有粒子 # 初始化一个粒子 def init_particle(self): x = [random.randint(0, 1) for i in range(self.problem.n)] # 随机生成一个个体 p = Particle(x) # 创建一个粒子对象 p.fitness = self.problem.fitness(p.x) # 计算个体的适应度 p.pbest = p.x[:] # 初始化个体最优解 p.pbest_fitness = p.fitness # 初始化个体最优解的适应度 return p # 初始化所有粒子 def init_particles(self): self.particles = [self.init_particle() for i in range(self.pop_size)] self.gbest = max(self.particles, key=lambda p: p.fitness) # 初始化全局最优解 # 更新粒子的速度和位置 def update_particle(self, p): r1, r2 = random.random(), random.random() # 生成两个随机数 for i in range(self.problem.n): p.v[i] = self.w * p.v[i] + self.c1 * r1 * (p.pbest[i] - p.x[i]) + self.c2 * r2 * (self.gbest.x[i] - p.x[i]) if p.v[i] > 1: # 速度限制在[-1, 1]范围内 p.v[i] = 1 elif p.v[i] < -1: p.v[i] = -1 p.x[i] = 1 if random.random() < sigmoid(p.v[i]) else 0 # 更新位置 p.fitness = self.problem.fitness(p.x) # 计算适应度 if p.fitness > p.pbest_fitness: # 更新个体最优解 p.pbest = p.x[:] p.pbest_fitness = p.fitness # 迭代粒子群 def iterate(self): for i in range(self.max_iter): for p in self.particles: self.update_particle(p) if p.fitness > self.gbest.fitness: # 更新全局最优解 self.gbest = p # 输出结果 def output(self): print("最优解:", self.gbest.x) print("最优解的适应度:", self.gbest.fitness) # 粒子类 class Particle: def __init__(self, x): self.x = x # 粒子的位置(即个体) self.v = [random.uniform(-1, 1) for i in range(len(x))] # 粒子的速度 self.fitness = 0 # 适应度(用于评价个体好坏) self.pbest = x[:] # 个体最优解 self.pbest_fitness = 0 # 个体最优解的适应度 # sigmoid函数 def sigmoid(x): return 1 / (1 + math.exp(-x)) # 测试 if __name__ == '__main__': n = 10 # 物品数量 c = 50 # 背包容量 w = [random.randint(1, 10) for i in range(n)] # 物品重量 v = [random.randint(1, 10) for i in range(n)] # 物品价值 problem = KnapsackProblem(n, c, w, v) pso = PSO(problem, pop_size=50, max_iter=100, c1=2, c2=2, w=0.8) pso.iterate() pso.output() ``` 代码中使用了sigmoid函数来把速度转换为位置,这样可以避免速度过大或过小导致的问题。代码还使用了粒子算法的经典公式来更新粒子的速度和位置。最后,我们可以通过运行代码来测试它的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值