传知代码-改进贪心算法(NGSOR)
一、算法背景及意义
(一)背包问题背景
背包问题是组合优化领域中的经典问题,具有广泛的实际应用场景,如资源分配、项目投资决策等。扩展简化折扣{0 - 1}背包问题(ESD{0 - 1}KP)是背包问题的一种变体,它在传统背包问题的基础上增加了一些复杂的约束条件,如物品的折扣系数以及每个项集中多个物品的选择情况,使得问题的求解更加困难。
(二)算法研究意义
- 理论意义:NGSOR算法为ESD{0 - 1}KP提供了一种有效的求解方法,通过将问题转化为与多选择背包问题(MCKP)相关的形式,并结合特定的计算价值密度和选择物品的策略,丰富了背包问题的求解算法理论。
- 实际意义:在实际应用中,能够帮助决策者在面对复杂的资源分配和项目选择问题时,更准确地找到满足约束条件且价值最大化的方案,提高决策效率和资源利用效率。
二、算法概述
(一)总体思路
NGSOR算法主要通过计算物品的价值密度,并根据价值密度从高到低的顺序选择物品,同时考虑物品的折扣系数和背包容量限制,逐步构建满足条件的最优物品组合。
(二)关键步骤
- 计算价值密度
- 对于每个项集中的物品,考虑不同的选择组合情况,计算出相应的价值和重量,进而得到价值密度。
- 选择物品
- 根据价值密度对所有可能的物品选择进行排序。
- 依次尝试选择每个物品,并检查选择后的物品组合是否满足背包容量限制。如果满足且总价值更大,则更新当前的最优物品组合。
三、算法详细步骤
(一)计算价值密度
- 在
calculate_value_density
函数中:- 首先获取物品价值系数数组
P
、质量系数数组W
和折扣系数数组d
的长度n
。 - 初始化一个形状为
(7*n, 2)
的二维数组E
,用于存储价值密度和原始索引信息。 - 对于每个项集(索引为
i
从0
到n - 1
):- 计算所有可能的物品选择组合的价值
Ps
,包括单个物品选择以及不同物品组合的情况。 - 计算相应的重量
Ws
,考虑了折扣系数的影响。 - 将计算得到的价值密度
Ps / Ws
存储在E
数组的对应行(7*i
到7*i + 7
)的第一列,同时将原始索引i
存储在第二列。
- 计算所有可能的物品选择组合的价值
- 首先获取物品价值系数数组
- 最终返回
E
数组,其中包含了所有物品选择组合的价值密度和原始索引信息。
(二)NGSOR算法主函数
- 在
NGSOR
函数中:- 获取物品价值系数数组
P
和质量系数数组W
的长度n
。 - 调用
calculate_value_density
函数计算价值密度数组E
。 - 将
E
数组与一个包含从1
到7*n
的索引数组进行列拼接,得到一个新的数组,用于后续排序和索引操作。 - 对新数组
E
按第一列(价值密度)进行降序排序,得到排序后的索引数组H
。 - 初始化决策变量数组
X
为全零数组,形状为(3*n, 1)
,用于表示物品的选择情况。同时初始化一些变量用于记录当前最优解的总价值、总重量以及对应的物品选择数组。
- 获取物品价值系数数组
- 然后进入循环:
- 对于每个可能的物品选择(索引为
i
从0
到7*n - 1
):- 根据排序后的索引
H[i]
计算物品所在项集索引t1
和在项集中的选择情况索引t2
,以及原始物品索引item_index
。 - 复制当前决策变量数组
X
得到T
,并根据t2
的值设置对应项集中物品的选择情况selection
。 - 计算选择
T
后的总重量Q
,通过遍历每个项集,检查是否有物品被选择,如果有则计算相应的重量并累加。 - 如果总重量
Q
满足背包容量限制C
:- 计算选择
T
后的总价值current_value
,通过将对应项集中物品的价值与选择情况相乘并累加得到。 - 如果
current_value
大于当前最优总价值best_value
,则更新最优解相关变量,包括最优物品选择数组best_X
、最优总价值best_value
和最优总重量best_weight
。
- 计算选择
- 根据排序后的索引
- 对于每个可能的物品选择(索引为
- 最后返回最优总价值
best_value
、最优总重量best_weight
和最优物品选择数组best_X
。
四、算法复杂度分析
(一)时间复杂度
- 在
calculate_value_density
函数中:- 有一个外层循环遍历
n
个项集,内部对于每个项集计算价值和重量组合需要常数时间(不考虑数组操作的时间复杂度),所以这部分时间复杂度为$O(n)$。
- 有一个外层循环遍历
- 在
NGSOR
函数中:- 计算价值密度的
calculate_value_density
函数调用时间复杂度为$O(n)$。 - 对价值密度数组
E
进行排序操作的时间复杂度通常为$O(7n log(7n))$,这里简化为$O(n log n)$(忽略常数系数)。 - 循环部分有
7n
次迭代,每次迭代内部计算物品选择情况、总重量和总价值的操作时间复杂度为$O(n)$(主要是遍历项集的操作),所以循环部分时间复杂度为$O(n^2)$。 - 综合来看,算法的时间复杂度主要由循环部分决定,为$O(n^2)$。
- 计算价值密度的
(二)空间复杂度
- 在
calculate_value_density
函数中:- 使用了一个形状为
(7*n, 2)
的数组E
,所以空间复杂度为$O(n)$(忽略常数系数)。
- 使用了一个形状为
- 在
NGSOR
函数中:- 使用了数组
E
、H
、X
、best_X
等,其中E
的大小为$O(n)$,H
的大小为$O(n)$(排序后的索引数组),X
和best_X
的大小为$O(n)$(因为是与项集数量相关的数组),所以空间复杂度为$O(n)$。
- 使用了数组
五、测试示例
- 在主函数中:
- 使用
np.random.seed(0)
设置随机数种子,确保结果的可重复性。 - 定义项集数量
n
为5
,随机生成价值系数数组P
(形状为(n, 3)
)、质量系数数组W
(形状为(n, 3)
)和折扣系数数组d
([1, 0.8, 0.7]
),以及背包最大载重C
为100
。
- 使用
- 调用
NGSOR
函数并输出结果,包括最优总价值Optimal Value
、最优总重量Optimal Weight
和最优物品选择数组Optimal Selection
(重塑为(n, 3)
的形状)。
通过上述文档,可以清晰地了解NGSOR
算法的复现过程,包括算法的背景意义、详细步骤、复杂度分析以及测试示例。
部署方式
- python 3.8以上