ga解決0-1背包問題,20個測試數據


  1 # 調試注意事項,當出現小數值時,可能時int位數設置不當,導致溢出
  2 import numpy
  3 import matplotlib.pyplot as plt
  4 
  5 
  6 data = numpy.array([[71, 34, 82, 23, 1,    88,    12,    57, 10, 68, 5, 33,    37,    69,    98,    24, 26,    83, 16, 26],
  7                     [26, 59, 30, 19, 66, 85, 94, 8, 3, 44, 5, 1, 41, 82, 76, 1,    12,    81,    73,    32]])
  8 
  9 data = data.T
 10 
 11 
 12 class GA(object):
 13     """
 14     遺傳算法解決0-1背包問題
 15     """
 16 
 17     def __init__(self, length, number, iter_number):
 18         """
 19         參數初始化
 20         :param length: 20
 21         :param number: 300
 22         :param iter_number: 200
 23         """
 24         self.length = length  # 確定染色體編碼長度
 25         self.number = number  # 確定初始化種群數量
 26         self.iteration = iter_number  # 設置迭代次數
 27         self.bag_capacity = 200  # 背包容量
 28 
 29         self.retain_rate = 0.2  # 每一代精英選擇出前20%
 30         self.random_selection_rate = 0.5  # 對於不是前20%的,有0.5的概率可以進行繁殖
 31         self.mutation_rate = 0.01  # 變異概率0.01
 32 
 33     def initial_population(self):
 34         """
 35         種群初始化,
 36 
 37         :return: 返回種群集合
 38         """
 39         init_population = numpy.random.randint(low=0, high=2, size=[self.length, self.number], dtype=numpy.int64)
 40         return init_population
 41 
 42     def weight_price(self, chromosome):
 43         """
 44         計算累計重量和累計價格
 45         :param chromosome:
 46         :return:返回每一個個體的累計重量和價格
 47         """
 48         w_accumulation = 0
 49         p_accumulation = 0
 50         for i in range(len(chromosome)):
 51 
 52             w = chromosome[i]*data[i][0]
 53             p = chromosome[i]*data[i][1]
 54             w_accumulation = w + w_accumulation
 55             p_accumulation = p + p_accumulation
 56 
 57         return w_accumulation, p_accumulation
 58 
 59     def fitness_function(self, chromosome):
 60         """
 61         計算適應度函數,一般來說,背包的價值越高越好,但是
 62         當重量超過100時,適應度函數=0
 63         :param chromosome:
 64         :return:
 65         """
 66 
 67         weight, price = self.weight_price(chromosome)
 68         if weight > self.bag_capacity:
 69             fitness = 0
 70         else:
 71             fitness = price
 72 
 73         return fitness
 74 
 75     def fitness_average(self, init_population):
 76         """
 77         求出這個種群的平均適應度,才能知道種群已經進化好了
 78         :return:返回的是一個種群的平均適應度
 79         """
 80         f_accumulation = 0
 81         for z in range(init_population.shape[1]):
 82             f_tem = self.fitness_function(init_population[:, z])
 83             f_accumulation = f_accumulation + f_tem
 84         f_accumulation = f_accumulation/init_population.shape[1]
 85         return f_accumulation
 86 
 87     def selection(self, init_population):
 88         """
 89         選擇
 90         :param init_population:
 91         :return: 返回選擇后的父代,數量是不定的
 92         """
 93         # sort_population = numpy.array([[], [], [], [], [], []])
 94         sort_population = numpy.empty(shape=[21, 0])  # 生成一個排序后的種群列表,暫時為空
 95         for i in range(init_population.shape[1]):
 96 
 97             x1 = init_population[:, i]
 98             # print('打印x1', x1)
 99             x2 = self.fitness_function(x1)
100             x = numpy.r_[x1, x2]
101             # print('打印x', x)
102             sort_population = numpy.c_[sort_population, x]
103 
104         sort_population = sort_population.T[numpy.lexsort(sort_population)].T  # 聯合排序,從小到大排列
105 
106         # print('排序后長度', sort_population.shape[1])
107         # print(sort_population)
108 
109         # 選出適應性強的個體,精英選擇
110         retain_length = sort_population.shape[1]*self.retain_rate
111 
112         # parents = numpy.array([[], [], [], [], [], []])  # 生成一個父代列表,暫時為空
113         parents = numpy.empty(shape=[21, 0])  # 生成一個父代列表,暫時為空
114         for j in range(int(retain_length)):
115             y1 = sort_population[:, -(j+1)]
116             parents = numpy.c_[parents, y1]
117 
118         # print(parents.shape[1])
119 
120         rest = sort_population.shape[1] - retain_length  # 精英選擇后剩下的個體數
121         for q in range(int(rest)):
122 
123             if numpy.random.random() < self.random_selection_rate:
124                 y2 = sort_population[:, q]
125                 parents = numpy.c_[parents, y2]
126 
127         parents = numpy.delete(parents, -1, axis=0)  # 刪除最后一行,刪除了f值
128         # print('打印選擇后的個體數')
129         # print(parents.shape[0])
130 
131         parents = numpy.array(parents, dtype=numpy.int64)
132 
133         return parents
134 
135     def crossover(self, parents):
136         """
137         交叉生成子代,和初始化的種群數量一致
138         :param parents:
139         :return:返回子代
140         """
141         # children = numpy.array([[], [], [], [], []])  # 子列表初始化
142         children = numpy.empty(shape=[20, 0])  # 子列表初始化
143 
144         while children.shape[1] < self.number:
145             father = numpy.random.randint(0, parents.shape[1] - 1)
146             mother = numpy.random.randint(0, parents.shape[1] - 1)
147             if father != mother:
148                 # 隨機選取交叉點
149                 cross_point = numpy.random.randint(0, self.length)
150                 # 生成掩碼,方便位操作
151                 mark = 0
152                 for i in range(cross_point):
153                     mark |= (1 << i)
154 
155                 father = parents[:, father]
156                 # print(father)
157                 mother = parents[:, mother]
158 
159                 # 子代將獲得父親在交叉點前的基因和母親在交叉點后(包括交叉點)的基因
160                 child = ((father & mark) | (mother & ~mark)) & ((1 << self.length) - 1)
161 
162                 children = numpy.c_[children, child]
163 
164                 # 經過繁殖后,子代的數量與原始種群數量相等,在這里可以更新種群。
165                 # print('子代數量', children.shape[1])
166         # print(children.dtype)
167         children = numpy.array(children, dtype=numpy.int64)
168         return children
169 
170     def mutation(self, children):
171         """
172         變異
173 
174         :return:
175         """
176         for i in range(children.shape[1]):
177 
178             if numpy.random.random() < self.mutation_rate:
179                 j = numpy.random.randint(0, self.length - 1)  # s隨機產生變異位置
180                 children[:, i] ^= 1 << j  # 產生變異
181         children = numpy.array(children, dtype=numpy.int64)
182         return children
183 
184     def plot_figure(self, iter_plot, f_plot, f_set_plot):
185         """
186         畫出迭代次數和平均適應度曲線圖
187         畫出迭代次數和每一步迭代最大值圖
188         :return:
189         """
190         plt.figure()
191 
192         ax1 = plt.subplot(121)
193         ax2 = plt.subplot(122)
194 
195         plt.sca(ax1)
196         plt.plot(iter_plot, f_plot)
197         plt.ylim(0, 400)  # 設置y軸范圍
198 
199         plt.sca(ax2)
200         plt.plot(iter_plot, f_set_plot)
201         plt.ylim(0, 400)  # 設置y軸范圍
202         plt.show()
203 
204     def main(self):
205         """
206         main函數,用來進化
207         對當前種群依次進行選擇、交叉並生成新一代種群,然后對新一代種群進行變異
208         :return:
209         """
210         init_population = self.initial_population()
211         # print(init_population)
212 
213         iter_plot = []
214         f_plot = []
215         iteration = 0
216 
217         f_set_plot = []
218 
219         while iteration < self.iteration:  # 設置迭代次數300
220 
221             parents = self.selection(init_population)  # 選擇后的父代
222             children = self.crossover(parents)
223             mutation_children = self.mutation(children)
224 
225             init_population = mutation_children
226 
227             f_set = []  # 求出每一步迭代的最大值
228             for init in range(init_population.shape[1]):
229                 f_set_tem = self.fitness_function(init_population[:, init])
230                 f_set.append(f_set_tem)
231 
232             f_set = max(f_set)
233 
234             f_set_plot.append(f_set)
235 
236             iter_plot.append(iteration)
237             iteration = iteration+1
238             print("第%s進化得如何******************************************" % iteration)
239             f_average = self.fitness_average(init_population)
240             f_plot.append(f_average)
241             print(f_set)
242             # f_accumulation = f_accumulation + f
243             # f_print = f_accumulation/(iteration + 1)
244             # print(f_print)
245         self.plot_figure(iter_plot, f_plot, f_set_plot)
246 
247 
248 if __name__ == '__main__':
249     g1 = GA(20, 300, 200)
250     g1.main()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM