├── .idea ├── .gitignore ├── CUMCM-Model-Learning.iml ├── encodings.xml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── AFSIndividual.py ├── LICENSE ├── NSGA-Ⅱ.py ├── ObjFunction.py ├── README.md ├── 人工蜂群算法.py ├── 人工鱼群算法.py ├── 免疫优化算法.py ├── 布谷鸟搜索算法.py ├── 模拟退火算法.py ├── 禁忌搜索算法.py ├── 粒子群算法.py ├── 细菌觅食优化算法.py ├── 萤火虫算法.py ├── 蚁群算法.py ├── 遗传算法.py └── 遗传算法_new.py /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/CUMCM-Model-Learning.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AFSIndividual.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ranxi2001/MCM-Model-Learning/5c4a991d4aa4f3c8fbf51f80a37e8f83b8f11754/AFSIndividual.py -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /NSGA-Ⅱ.py: -------------------------------------------------------------------------------- 1 | # Program Name: NSGA-II.py 2 | # Description: This is a python implementation of Prof. Kalyanmoy Deb's popular NSGA-II algorithm 3 | 4 | #Importing required modules 5 | import math 6 | import random 7 | import matplotlib.pyplot as plt 8 | 9 | #First function to optimize 10 | def function1(x): 11 | value = -x**2 12 | return value 13 | 14 | #Second function to optimize 15 | def function2(x): 16 | value = -(x-2)**2 17 | return value 18 | 19 | #Function to find index of list 20 | def index_of(a,list): 21 | for i in range(0,len(list)): 22 | if list[i] == a: 23 | return i 24 | return -1 25 | 26 | #Function to sort by values 给个体排序 27 | def sort_by_values(list1, values): 28 | sorted_list = [] 29 | while(len(sorted_list) != len(list1)): 30 | if index_of(min(values), values) in list1: 31 | sorted_list.append(index_of(min(values),values)) 32 | values[index_of(min(values), values)] = math.inf 33 | return sorted_list 34 | 35 | #Function to carry out NSGA-II's fast non dominated sort 36 | # 实现NSGA-II的快速非支配排序,最后返回的是一组非支配解,即Pareto前沿 37 | def fast_non_dominated_sort(values1, values2): 38 | S = [[] for i in range(0, len(values1))] # S用来记录种群中被个体p支配的个体的集合,因为有20个个体,所以会有20个[] 39 | front = [[]] 40 | n = [0 for i in range(0,len(values1))] # n用来记录种群中支配个体 p 的个体数 41 | rank = [0 for i in range(0, len(values1))] 42 | #对种群中每一个个体,都进行n和s集合的计算 43 | for p in range(0, len(values1)): 44 | S[p] = [] #最初的时候,对于每一个个体,S[p]都是空的 45 | n[p] = 0 #最初的时候,对于每一个个体,n[p]都是0 46 | for q in range(0, len(values1)): 47 | # 然后开始对每一个个体p,都遍历种群,找出其支配的个体,存到S中,找到支配p的个体,将其数量存在n中 48 | if (values1[p] > values1[q] and values2[p] > values2[q]) or (values1[p] >= values1[q] and values2[p] > values2[q]) or (values1[p] > values1[q] and values2[p] >= values2[q]): 49 | #这个判断关系是说 p支配q,因此可以将q存在S[p]中,前提是满足单一性。 50 | if q not in S[p]: 51 | S[p].append(q) 52 | elif (values1[q] > values1[p] and values2[q] > values2[p]) or (values1[q] >= values1[p] and values2[q] > values2[p]) or (values1[q] > values1[p] and values2[q] >= values2[p]): 53 | #否则的话就是p被支配,n计数+1 54 | n[p] = n[p] + 1 55 | if n[p] == 0: #如果n[p] = 0,说明p是一个非支配解,将它的rank的级别设为最低,这样后面的虚拟适应度值才会最高 56 | rank[p] = 0 57 | if p not in front[0]: #同时将此解加入到Pareto前沿中,此时front[0]中都是最开始产生的非支配解,我们可以将其称之为F1 58 | front[0].append(p) 59 | 60 | i = 0 61 | while(front[i] != []): #记住这个循环条件,是用来判断整个种群有咩有被全部分级的。 62 | Q = [] 63 | for p in front[i]: 64 | for q in S[p]: 65 | #对于当前集合F1中的每一个个体p其所支配的个体集合s[p],遍历s[p]中的每一个个体q,执行n[q]-1,如果此时nq=0,就将个体q保存在集合Q中,同时q的等价+1 66 | n[q] =n[q] - 1 67 | if( n[q]==0): 68 | rank[q] = i+1 69 | if q not in Q: 70 | Q.append(q) 71 | i = i+1 72 | #记F1中得到的个体,即front[0]中的个体为第一个非支配层的个体,并以Q为当前集合,重复上述操作,一直到整个种群被分级。 73 | front.append(Q) 74 | 75 | del front[len(front)-1] 76 | return front 77 | 78 | #Function to calculate crowding distance 79 | # 拥挤因子 80 | def crowding_distance(values1, values2, front): 81 | #crowding_distance(function1_values[:], function2_values[:], non_dominated_sorted_solution[i][:]) 82 | #来看看 同属于一个非支配层的两个个体之间的 拥挤度是怎么计算的 83 | 84 | #先取出当前非支配层的所有个体,一共有len(front) 85 | distance = [0 for i in range(0, len(front))] 86 | #对于每一个目标函数 87 | # (1)基于该目标函数对种群进行排序 88 | sorted1 = sort_by_values(front, values1[:]) 89 | sorted2 = sort_by_values(front, values2[:]) 90 | #(2)令边界的两个个体拥挤度位无穷 91 | distance[0] = 4444444444444444 92 | distance[len(front) - 1] = 4444444444444444 93 | #(3)distance[k]从第二个个体开始,计算distance[k] = distance[k] + [(fm(i+1)-fm(i-1))] / (max - min) 94 | for k in range(1, len(front)-1): 95 | distance[k] = distance[k] + (values1[sorted1[k+1]] - values2[sorted1[k-1]])/(max(values1)-min(values1)) 96 | for k in range(1, len(front)-1): 97 | distance[k] = distance[k] + (values1[sorted2[k+1]] - values2[sorted2[k-1]])/(max(values2)-min(values2)) 98 | #最后返回distance集合,里面存放的是每一个非支配层的每一个个体的拥挤度。 99 | return distance 100 | 101 | #Function to carry out the crossover 102 | # 交叉算子 103 | def crossover(a,b): 104 | r=random.random() 105 | if r>0.5: 106 | return mutation((a+b)/2) 107 | else: 108 | return mutation((a-b)/2) 109 | 110 | #Function to carry out the mutation operator 111 | # 变异算子 112 | def mutation(solution): 113 | mutation_prob = random.random() 114 | if mutation_prob <1: 115 | solution = min_x+(max_x-min_x)*random.random() 116 | return solution 117 | 118 | #Main program starts here 119 | pop_size = 20 120 | max_gen = 921 121 | 122 | #Initialization 123 | min_x = -55 124 | max_x = 55 125 | #产生初始种群,范围在【-55,55】之间,这里只考虑了一个维度,因为只有一个自变量x 126 | solution = [min_x+(max_x-min_x)*random.random() for i in range(0, pop_size)] 127 | print("solutiob:", solution) 128 | gen_no = 0 129 | while (gen_no < max_gen): 130 | 131 | #计算每一迭代过程中的初始种群的适应度值 132 | function1_values = [function1(solution[i])for i in range(0, pop_size)] 133 | function2_values = [function2(solution[i])for i in range(0, pop_size)] 134 | print("function_values_size", len(function1_values)) #20 135 | non_dominated_sorted_solution = fast_non_dominated_sort(function1_values[:], function2_values[:]) 136 | #返回的是当前代的非支配解的分级表示。 137 | print("当前非支配解分级的个数:", len(non_dominated_sorted_solution)) #分级的个数是不断在改变的,一直到最后只有一个 138 | print("The best front for Generation number ", gen_no, " is") 139 | for valuez in non_dominated_sorted_solution[0]: 140 | #遍历第一级别的非支配解个体 141 | print(round(solution[valuez], 3), end=" ") #round() 方法返回浮点数x的四舍五入值。3是保留3位小数 142 | 143 | #接下来,拥挤度计算与比较 144 | crowding_distance_values = [] 145 | for i in range(0, len(non_dominated_sorted_solution)):#遍历每一个非支配层 146 | #non_dominated_sorted_solution[i][:]代表的是第i个非支配层的所有个体 147 | #首先计算出同属于一个非支配层的个体i 其他个体之间的欧几里得距离,然后将其存在 148 | crowding_distance_values.append(crowding_distance(function1_values[:], function2_values[:], non_dominated_sorted_solution[i][:])) 149 | #每一个非支配层都应该有一个拥挤度的 150 | print("拥挤度的大小", len(crowding_distance_values)) 151 | print("\n") 152 | 153 | solution2 = solution[:] # 此时当第一次执行时,此时的solution2和初始种群一样 154 | print("solutiob2:", solution2) 155 | 156 | #Generating offsprings 生成子种群 157 | while(len(solution2) != 2 * pop_size): #当当前种群的数量不是原本的2倍的时候,表示现在还没有产生子代,那么就产生子代 158 | a1 = random.randint(0, pop_size-1) 159 | b1 = random.randint(0, pop_size-1) 160 | solution2.append(crossover(solution[a1],solution[b1])) 161 | # print("此时solution2的大小:", len(solution2)) 已经翻倍 162 | 163 | # 此时子父代已经合并了,但是还没有生成新的父种群 164 | function1_values2 = [function1(solution2[i])for i in range(0, 2*pop_size)] 165 | function2_values2 = [function2(solution2[i])for i in range(0, 2*pop_size)] 166 | # 对合并过后的种群进行快速非支配排序以及拥挤度的计算 167 | non_dominated_sorted_solution2 = fast_non_dominated_sort(function1_values2[:], function2_values2[:]) 168 | crowding_distance_values2 = [] 169 | for i in range(0, len(non_dominated_sorted_solution2)): 170 | crowding_distance_values2.append(crowding_distance(function1_values2[:], function2_values2[:], non_dominated_sorted_solution2[i][:])) 171 | # 然后选择合适的个体组成新的父种群,每一迭代的过程都是如此 172 | # 通过快速非支配排序以及拥挤度计算之后,种群中的每一个个体n都得到两个属性,非支配序rank 和 拥挤度 distance 173 | new_solution = [] 174 | for i in range(0, len(non_dominated_sorted_solution2)): #遍历每一个非支配层 175 | # 176 | non_dominated_sorted_solution2_1 = [index_of(non_dominated_sorted_solution2[i][j], non_dominated_sorted_solution2[i]) for j in range(0, len(non_dominated_sorted_solution2[i]))] 177 | # print("得到第", i, "非支配层的解个体的索引", non_dominated_sorted_solution2_1) 178 | front22 = sort_by_values(non_dominated_sorted_solution2_1[:], crowding_distance_values2[i][:]) 179 | # print("对其按照拥挤度进行排序:", front22) 180 | # 遍历当前非支配层中的每一个个体j, 181 | front = [non_dominated_sorted_solution2[i][front22[j]] for j in range(0, len(non_dominated_sorted_solution2[i]))] 182 | front.reverse() 183 | for value in front: 184 | new_solution.append(value) 185 | if(len(new_solution)==pop_size): 186 | break 187 | if (len(new_solution) == pop_size): 188 | break 189 | solution = [solution2[i] for i in new_solution] 190 | gen_no = gen_no + 1 191 | 192 | # Lets plot the final front now 193 | # 加负号是将最大值问题转化为最小值问题,即求 x**2 和 (x-2)**2 的最小值 194 | function1 = [i * -1 for i in function1_values] 195 | function2 = [j * -1 for j in function2_values] 196 | 197 | plt.xlabel('Function 1', fontsize=15) 198 | plt.ylabel('Function 2', fontsize=15) 199 | plt.scatter(function1, function2) 200 | plt.show() 201 | -------------------------------------------------------------------------------- /ObjFunction.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | def GrieFunc(vardim, x, bound): 5 | """ 6 | Griewangk function 7 | """ 8 | s1 = 0. 9 | s2 = 1. 10 | for i in range(1, vardim + 1): 11 | s1 = s1 + x[i - 1] ** 2 12 | s2 = s2 * math.cos(x[i - 1] / math.sqrt(i)) 13 | y = (1. / 4000.) * s1 - s2 + 1 14 | y = 1. / (1. + y) 15 | return y 16 | 17 | 18 | def RastFunc(vardim, x, bound): 19 | """ 20 | Rastrigin function 21 | """ 22 | s = 10 * 25 23 | for i in range(1, vardim + 1): 24 | s = s + x[i - 1] ** 2 - 10 * math.cos(2 * math.pi * x[i - 1]) 25 | return s -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CUMCM-Model-Learning 2 | 3 | 这是我用来学习数学建模算法的仓库,去年数模国赛智能优化算法仅仅学了模拟退火,导致国赛算法选择很被动,这次我要在今年国赛前学习更多的算法,有备无患,万事俱备只欠东风! 4 | 5 | -------------------------------------------------------------------------------- /人工蜂群算法.py: -------------------------------------------------------------------------------- 1 | import random, math, copy 2 | import matplotlib.pyplot as plt 3 | from mpl_toolkits.mplot3d import Axes3D 4 | import numpy as np 5 | 6 | plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 7 | plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 8 | """ 9 | def GrieFunc(data): # 目标函数 10 | s1 = 0. 11 | s2 = 1. 12 | for k, x in enumerate(data): #enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标 13 | #产生25个x 14 | s1 = s1 + x ** 2 15 | print("k:", k) 16 | print("x:", x) 17 | s2 = s2 * math.cos(x / math.sqrt(k + 1)) 18 | y = (1. / 4000.) * s1 - s2 + 1 19 | return 1. / (1. + y) 20 | """ 21 | 22 | 23 | def GrieFunc(data): # 目标函数 24 | s1 = 0 25 | for k, x in enumerate(data): # enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标 26 | s1 = s1 + x 27 | y = s1 28 | return y 29 | 30 | 31 | class ABSIndividual: # 初始化,怎么初始化呢? 32 | def __init__(self, bound): 33 | self.score = 0. 34 | self.invalidCount = 0 # 无效次数(成绩没有更新的累积次数) 35 | # 由于这里的目标函数是一元的,因此这个chrom是一维数组。如果是二元函数,chrom就要变化 36 | self.chrom = [random.uniform(a, b) for a, b in 37 | zip(bound[0, :], bound[1, :])] # 随机初始化 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表 38 | # random.uniform(a, b)返回a,b之间的随机浮点数,在本例中,返回-500到500之间的数,若a<=b则范围[a,b],若a>=b则范围[b,a] ,a和b可以是实数。 39 | # 即一个chrom是一个有25个数值的数组,这样就完成了初始化,在25维的空间中各产生了一个x,因为目标函数是一元函数。 40 | # a=[1,2,3] b=[4,5,6] zip(a,b) = [(1,4),(2,5),(3,6) ] 41 | self.calculateFitness() 42 | # for a, b in zip(bound[0, :], bound[1, :]): #循环了30遍,正好是初始化蜂群蜜源的大小。 43 | # print("a:", a) #产生25个a #正好是vardim ,变量的维度, 44 | 45 | def calculateFitness(self): 46 | # print("chrom:", len(self.chrom)) 47 | self.score = GrieFunc(self.chrom) # 计算当前成绩 48 | 49 | 50 | class ArtificialBeeSwarm: 51 | def __init__(self, foodCount, onlookerCount, bound, maxIterCount=1000, maxInvalidCount=200): 52 | # abs = ArtificialBeeSwarm(30, 30, bound, 1000, 200) 53 | self.foodCount = foodCount # 蜜源个数,等同于雇佣蜂数目 54 | self.onlookerCount = onlookerCount # 观察蜂个数 55 | self.bound = bound # 各参数上下界 56 | self.maxIterCount = maxIterCount # 迭代次数 57 | self.maxInvalidCount = maxInvalidCount # 最大无效次数 以此来判断是否丢失蜜源 58 | self.foodList = [ABSIndividual(self.bound) for k in 59 | range(self.foodCount)] # 初始化各蜜源,就本例来说,如果设定蜜源个数为30,维度为15,那么这个蜜源应该是在每一维里面都有30个采蜜蜂。 60 | self.foodScore = [d.score for d in 61 | self.foodList] # 各蜜源最佳成绩 #将每一个蜜源的适应度值按照目标函数计算,保存在foodScore里面,所以foodScore的维度也是30 62 | # self.bestFood = self.foodList[np.argmax(self.foodScore)] # 全局最佳蜜源,找最大值 63 | self.bestFood = self.foodList[np.argmin(self.foodScore)] 64 | 65 | def updateFood(self, i): # 更新第i个蜜源 66 | k = random.randint(0, self.bound.shape[1] - 1) # 随机选择调整参数的维度 67 | # 下面是寻找新蜜源的公式,ppt第9张。 68 | j = random.choice([d for d in range(self.foodCount) if d != i]) # random.choice从序列中获取一个随机元素; 69 | vi = copy.deepcopy(self.foodList[i]) 70 | # print("第i个蜜源的适应度值", foodList[i].score) 71 | vi.chrom[k] += random.uniform(-1.0, 1.0) * (vi.chrom[k] - self.foodList[j].chrom[k]) # 调整参数 72 | 73 | vi.chrom[k] = np.clip(vi.chrom[k], self.bound[0, k], self.bound[1, k]) # 参数不能越界 74 | vi.calculateFitness() # 计算新蜜源的适应度值 75 | """ 76 | if vi.score > self.foodList[i].score: # 如果新蜜源的适应度值比当前蜜源好 77 | self.foodList[i] = vi 78 | if vi.score > self.foodScore[i]: # 如果新蜜源的适应度值 比历史成绩好(如重新初始化,当前成绩可能低于历史成绩) 79 | self.foodScore[i] = vi.score 80 | if vi.score > self.bestFood.score: # 如果成绩全局最优 81 | self.bestFood = vi 82 | self.foodList[i].invalidCount = 0 #当前蜜源进行了更新 83 | else: 84 | self.foodList[i].invalidCount += 1 #当前蜜源没有进行更新 85 | """ 86 | if vi.score < self.foodList[i].score: # 如果新蜜源的适应度值比当前蜜源好 87 | self.foodList[i] = vi 88 | if vi.score < self.foodScore[i]: # 如果新蜜源的适应度值 比历史成绩好(如重新初始化,当前成绩可能低于历史成绩) 89 | self.foodScore[i] = vi.score 90 | if vi.score < self.bestFood.score: # 如果成绩全局最优 91 | self.bestFood = vi 92 | self.foodList[i].invalidCount = 0 # 当前蜜源进行了更新 93 | else: 94 | self.foodList[i].invalidCount += 1 # 当前蜜源没有进行更新 95 | 96 | def employedBeePhase(self): # 雇佣蜂,即采蜜蜂的行为:寻找新蜜源 97 | for i in range(0, self.foodCount): # 各蜜源依次更新 98 | self.updateFood(i) # 从初始化的那群采蜜蜂开始,产生新的解,即产生新的蜜源 99 | 100 | def onlookerBeePhase(self): # 跟随蜂,即观察蜂的行为:应用轮盘赌算法选取蜜源, 101 | foodScore = [d.score for d in self.foodList] 102 | maxScore = np.min(foodScore) 103 | accuFitness = [(0.9 * d / maxScore + 0.1, k) for k, d in enumerate(foodScore)] # 得到各蜜源的 相对分数和索引号 104 | # print("得到各蜜源的相对分数和索引号", accuFitness) 105 | for k in range(0, self.onlookerCount): 106 | i = random.choice([d[1] for d in accuFitness if 107 | d[0] >= random.random()]) # 随机从相对分数大于随机门限的蜜源中选择跟随,选中蜜源i,同时更新蜜源i,即获得蜜源周围的新蜜源,然后与此比较 108 | self.updateFood(i) 109 | 110 | def scoutBeePhase(self): # 探索蜂,即侦查蜂的行为:用来侦查某一蜜源是否应该丢弃,比如蜜源i应该被丢弃,那么,重新对这个蜜源进行初始化,以及记录新的适应度值 111 | for i in range(0, self.foodCount): 112 | if self.foodList[i].invalidCount > self.maxInvalidCount: # 如果该蜜源没有更新的次数超过指定门限,则重新初始化 113 | self.foodList[i] = ABSIndividual(self.bound) 114 | self.foodScore[i] = min(self.foodScore[i], self.foodList[i].score) 115 | 116 | def solve(self): 117 | trace = [] 118 | trace.append((self.bestFood.score, np.mean(self.foodScore))) 119 | for k in range(self.maxIterCount): # 迭代次数,每迭代一次:就进行这三种动作,三种行为结束之后,将当前的最优适应度值存进trace中, 120 | self.employedBeePhase() 121 | self.onlookerBeePhase() 122 | self.scoutBeePhase() 123 | trace.append((self.bestFood.score, np.mean(self.foodScore))) 124 | print(self.bestFood.score) 125 | self.printResult(np.array(trace)) 126 | 127 | def printResult(self, trace): 128 | x = np.arange(0, trace.shape[0]) 129 | plt.plot(x, [(1 - d) / d for d in trace[:, 0]], 'r', label='optimal value') 130 | plt.plot(x, [(1 - d) / d for d in trace[:, 1]], 'g', label='average value') 131 | plt.xlabel("Iteration") 132 | plt.ylabel("function value") 133 | plt.title("Artificial Bee Swarm algorithm for function optimization") 134 | plt.legend() 135 | plt.show() 136 | 137 | 138 | if __name__ == "__main__": 139 | random.seed() 140 | vardim = 7 # 和向目标函数中传入的data的维度一样 141 | bound = np.tile([[-500], [500]], vardim) 142 | abs = ArtificialBeeSwarm(30, 30, bound, 1000, 500) 143 | abs.solve() 144 | -------------------------------------------------------------------------------- /人工鱼群算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import copy 3 | import matplotlib.pyplot as plt 4 | from AFSIndividual import AFSIndividual 5 | """ 6 | 人工鱼群算法步骤: 7 | (1)初始化: 8 | 初始化参数:种群规模popsize;人工鱼的视野Visual;人工鱼的步长step;拥挤度因子;重复次数 9 | 初始化鱼群: 10 | (2)计算鱼群中每条鱼的适应度,并将鱼群中最优适应度值以及对应的鱼的位置保存,我们称之为 公告牌 11 | (3)鱼群进行 聚群行为或者跟随行为(选择那种行为根据聚群行为和跟随行为发生之后的适应度值来决定): 12 | 如果聚群行为之后的适应度值大,该鱼就进行聚群行为 13 | 如果跟随行为之后的适应度值大,该鱼就进行跟随行为 14 | (3.1)聚群行为:人工鱼探索当前邻域内的伙伴数量,并计算伙伴的中心位置,然后把新得到的中心位置的目标函数与当前位置的目标函数相比较, 15 | 如果中心位置的目标函数优于当前位置的目标函数并且不是很拥挤,则当前位置向中心位置移动一步,否则执行觅食行为。 16 | (3.1)跟随行为:人工鱼搜索周围邻域内鱼的最优位置,当最优位置的目标函数值大于当前位置的目标函数值并且不是很拥挤,则当前位置向最优邻域鱼移动一步, 17 | 否则执行觅食行为。 18 | (4)选择某种行为之后,计算种群适应度,并将鱼群中最优适应度值与公告牌比较,如果优于公告牌,则更新公告牌的状态 19 | (5)判断是否满足终止条件,如果满足,输出最优解,如果不满足,继续(3)(4) 20 | 21 | """ 22 | 23 | class ArtificialFishSwarm: 24 | def __init__(self, sizepop, vardim, bound, MAXGEN, params): 25 | # params[0]=visual params[1]=step params[2]=拥挤度因子 params[3]=重复次数 26 | # fa = ArtificialFishSwarm(60, 25, bound, 1000, [0.001, 0.0001, 0.618, 40]) 27 | self.sizepop = sizepop 28 | self.vardim = vardim 29 | self.bound = bound 30 | self.MAXGEN = MAXGEN 31 | self.params = params 32 | self.population = [] 33 | self.fitness = np.zeros((self.sizepop, 1)) 34 | self.trace = np.zeros((self.MAXGEN, 2)) 35 | self.lennorm = 6000 36 | 37 | # 初始化种群 38 | def initialize(self): 39 | for i in range(0, self.sizepop): 40 | ind = AFSIndividual(self.vardim, self.bound) 41 | ind.generate() 42 | self.population.append(ind) 43 | 44 | 45 | def evaluation(self, x): 46 | x.calculateFitness() 47 | 48 | # 人工鱼觅食行为 49 | def forage(self, x): 50 | newInd = copy.deepcopy(x) 51 | found = False 52 | # 觅食行为:设置人工鱼当前的状态,并在其感知范围内随机选择另一个状态, 53 | for i in range(0, self.params[3]): 54 | indi = self.randSearch(x, self.params[0]) # 并在其感知范围内随机选择另一个状态, 55 | # 如果得到的新状态indi的目标函数大于当前的状态,则向新选择得到的状态靠近一步,反之,重新随机选择状态,如此循环 56 | if indi.fitness > x.fitness: 57 | newInd.individual = x.individual + np.random.random(self.vardim) * self.params[1] * self.lennorm * ( 58 | indi.individual - x.individual) / np.linalg.norm(indi.individual - x.individual) 59 | newInd = indi 60 | found = True 61 | break 62 | # 如果选择次数达到一定数量之后,状态仍没有改变,则随机移动一步 63 | if not (found): 64 | newInd = self.randSearch(x, self.params[1]) 65 | return newInd 66 | 67 | # 人工鱼随机行为 68 | def randSearch(self, x, searLen): 69 | 70 | ind = copy.deepcopy(x) 71 | ind.individual += np.random.uniform(-1, 1, self.vardim) * searLen * self.lennorm 72 | for j in range(0, self.vardim): 73 | if ind.individual[j] < self.bound[0, j]: 74 | ind.individual[j] = self.bound[0, j] 75 | if ind.individual[j] > self.bound[1, j]: 76 | ind.individual[j] = self.bound[1, j] 77 | self.evaluation(ind) 78 | return ind 79 | 80 | # 人工鱼聚群行为 81 | def huddle(self, x): 82 | newInd = copy.deepcopy(x) 83 | dist = self.distance(x) 84 | index = [] 85 | for i in range(1, self.sizepop): 86 | if dist[i] > 0 and dist[i] < self.params[0] * self.lennorm: 87 | index.append(i) 88 | nf = len(index) 89 | if nf > 0: 90 | xc = np.zeros(self.vardim) 91 | for i in range(0, nf): 92 | xc += self.population[index[i]].individual 93 | xc = xc / nf 94 | cind = AFSIndividual(self.vardim, self.bound) 95 | cind.individual = xc 96 | cind.calculateFitness() 97 | # 聚集行为: 人工鱼探索当前邻域内的伙伴数量,并计算伙伴的中心位置,然后把新得到的中心位置的目标函数与当前位置的目标函数相比较 98 | 99 | # 如果中心位置的目标函数 优于当前位置的目标函数 并且不是很拥挤,那么当前位置向中心位置移动一步 100 | if (cind.fitness / nf) > (self.params[2] * x.fitness): 101 | xnext = x.individual + np.random.random( 102 | self.vardim) * self.params[1] * self.lennorm * (xc - x.individual) / np.linalg.norm(xc - x.individual) 103 | for j in range(0, self.vardim): 104 | if xnext[j] < self.bound[0, j]: 105 | xnext[j] = self.bound[0, j] 106 | if xnext[j] > self.bound[1, j]: 107 | xnext[j] = self.bound[1, j] 108 | newInd.individual = xnext 109 | self.evaluation(newInd) 110 | print("hudding") 111 | return newInd 112 | # 否则:即中心位置的目标函数 不优于当前位置的目标函数,那么当前位置不移动,而是执行觅食行为 113 | else: 114 | return self.forage(x) 115 | else: 116 | return self.forage(x) 117 | 118 | # 人工鱼追尾行为 119 | def follow(self, x): 120 | newInd = copy.deepcopy(x) 121 | dist = self.distance(x) 122 | index = [] 123 | for i in range(1, self.sizepop): 124 | if dist[i] > 0 and dist[i] < self.params[0] * self.lennorm: 125 | index.append(i) 126 | nf = len(index) 127 | if nf > 0: 128 | best = -999999999. 129 | bestIndex = 0 130 | for i in range(0, nf): 131 | if self.population[index[i]].fitness > best: 132 | best = self.population[index[i]].fitness 133 | bestIndex = index[i] 134 | # 人工鱼搜索周围邻域内鱼的最优位置,当最优位置的目标函数值大于当前位置的目标函数值并且不是很拥挤, 135 | # 那么当前位置向最优邻域鱼移动一步 136 | if (self.population[bestIndex].fitness / nf) > (self.params[2] * x.fitness): 137 | xnext = x.individual + np.random.random( 138 | self.vardim) * self.params[1] * self.lennorm * ( 139 | self.population[bestIndex].individual - x.individual) / np.linalg.norm( 140 | self.population[bestIndex].individual - x.individual) 141 | for j in range(0, self.vardim): 142 | if xnext[j] < self.bound[0, j]: 143 | xnext[j] = self.bound[0, j] 144 | if xnext[j] > self.bound[1, j]: 145 | xnext[j] = self.bound[1, j] 146 | newInd.individual = xnext 147 | self.evaluation(newInd) 148 | # print "follow" 149 | return newInd 150 | # 否则,即人工鱼搜索周围邻域内鱼的最优位置,当最优位置的目标函数值不大于当前位置的目标函数值,执行觅食行为 151 | else: 152 | return self.forage(x) 153 | else: 154 | return self.forage(x) 155 | 156 | def solve(self): 157 | self.t = 0 158 | self.initialize() 159 | print("产生的初始化种群:", self.population) # 60 sizepop 行 25 vardim 列 160 | # 评估人工鱼群 161 | for i in range(0, self.sizepop): 162 | self.evaluation(self.population[i]) 163 | # 计算每条鱼的适应度值 164 | self.fitness[i] = self.population[i].fitness 165 | bestIndex = np.argmax(self.fitness) # 用于返回一个numpy数组中最大值的索引值,相当于公告牌 166 | self.best = copy.deepcopy(self.population[bestIndex]) # 相当于公告牌 167 | self.avefitness = np.mean(self.fitness) 168 | self.trace[self.t, 0] = (1 - self.best.fitness) / self.best.fitness 169 | self.trace[self.t, 1] = (1 - self.avefitness) / self.avefitness 170 | print("Generation %d: optimal function value is: %f; average function value is %f" % (self.t, self.trace[self.t, 0], self.trace[self.t, 1])) 171 | while self.t < self.MAXGEN - 1: 172 | # 迭代循环开始 173 | self.t += 1 174 | # newpop = [] 175 | for i in range(0, self.sizepop): 176 | xi1 = self.huddle(self.population[i]) # 聚群行为,对于每一条鱼让其进行聚群 177 | xi2 = self.follow(self.population[i]) # 跟随行为,对于每一条鱼让其进行跟随 178 | # 将聚群行为和跟随行为产生的适应度进行对比 179 | if xi1.fitness > xi2.fitness: # 如果聚群行为得到的适应度值更大,当前鱼选择聚群行为 180 | self.population[i] = xi1 181 | self.fitness[i] = xi1.fitness 182 | else: # 否则当前鱼i选择跟随行为 183 | self.population[i] = xi2 184 | self.fitness[i] = xi2.fitness 185 | best = np.max(self.fitness) 186 | bestIndex = np.argmax(self.fitness) # 记录当前鱼群中最优适应度值 187 | if best > self.best.fitness: # 如果当前代的鱼群的最优适应度比公告牌中的还优 188 | self.best = copy.deepcopy(self.population[bestIndex]) # 那么就将公告牌中的状态和值更换 189 | self.avefitness = np.mean(self.fitness) 190 | self.trace[self.t, 0] = (1 - self.best.fitness) / self.best.fitness 191 | self.trace[self.t, 1] = (1 - self.avefitness) / self.avefitness 192 | print("Generation %d: optimal function value is: %f; average function value is %f" % ( 193 | self.t, self.trace[self.t, 0], self.trace[self.t, 1])) 194 | print("Optimal function value is: %f; " % self.trace[self.t, 0]) 195 | print("Optimal solution is:") 196 | print(self.best.individual) 197 | self.printResult() 198 | 199 | def distance(self, x): 200 | dist = np.zeros(self.sizepop) 201 | for i in range(0, self.sizepop): 202 | dist[i] = np.linalg.norm(x.individual - self.population[i].individual) / 6000 203 | return dist 204 | 205 | def printResult(self): 206 | x = np.arange(0, self.MAXGEN) 207 | y1 = self.trace[:, 0] 208 | y2 = self.trace[:, 1] 209 | plt.plot(x, y1, 'r', label='optimal value') 210 | plt.plot(x, y2, 'g', label='average value') 211 | plt.xlabel("Iteration") 212 | plt.ylabel("function value") 213 | plt.title("Artificial Fish Swarm algorithm for function optimization") 214 | plt.legend() 215 | plt.show() 216 | 217 | 218 | if __name__ == "__main__": 219 | bound = np.tile([[-600], [600]], 25) 220 | fa = ArtificialFishSwarm(60, 25, bound, 1000, [0.001, 0.0001, 0.618, 40]) 221 | fa.solve() 222 | -------------------------------------------------------------------------------- /免疫优化算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import pyplot as plt 3 | from mpl_toolkits.mplot3d import Axes3D 4 | 5 | """ 6 | 免疫优化算法步骤: 7 | (1)初始化: 8 | 初始化参数:抗体种群N(10-100); 最大进化代数(100-500);变异概率 9 | 初始化抗体种群: 10 | (2)计算亲和度:亲和度评价算子 11 | (3)计算抗体浓度和激励度:抗体浓度评价算子,激励度计算算子 12 | (4)免疫选择:免疫选择算子 13 | (5)克隆、变异、克隆抑制:克隆算子、变异算子、克隆抑制算子 14 | (6)种群刷新:种群刷新算子 15 | (7)判断是否满足终止条件,满足输出最优解,不满足回到(2) 16 | """ 17 | 18 | 19 | class IA: 20 | def __init__(self, G=100, pop_size=50, mutate_rate=0.7, delta=0.2, beta=1, colone_num=10): 21 | self.G = G # 迭代次数 22 | self.dim = 2 # 自变量个数 23 | self.limit_x = [-4, 4] # x取值范围 24 | self.limit_y = [-4, 4] # y取值范围 25 | self.choice = 'max' 26 | self.pop_size = pop_size # 种群规模 27 | self.mutate_rate = mutate_rate # 变异概率 28 | self.delta = delta # 相似度阈值 29 | self.beta = beta # 激励度系数 30 | self.colone_num = colone_num # colone_num = 10 # 克隆份数 31 | if self.choice == 'max': 32 | self.alpha = 2 # 激励度系数,求最大值为正,最小值为负 33 | else: 34 | self.alpha = -2 35 | 36 | def func(self, x, y): # 亲和度计算 37 | fx = 5 * np.sin(x * y) + x ** 2 + y ** 2 38 | return fx 39 | 40 | # 初始化种群 41 | def init_pop(self, dim, pop_size, *limit): 42 | pop = np.random.rand(dim, pop_size) 43 | for i in range(dim): 44 | pop[i, :] *= (limit[i][1] - limit[i][0]) 45 | pop[i, :] += limit[i][0] 46 | return pop 47 | 48 | # 抗体浓度评价算子:计算浓度 49 | def calc_density(self, pop, delta): # 需要一个相似度阈值:delta 50 | density = np.zeros([pop.shape[1], ]) 51 | for i in range(pop.shape[1]): 52 | density[i] = np.sum( 53 | len(np.ones([pop.shape[1], ])[np.sqrt(np.sum((pop - pop[:, i].reshape([2, 1])) ** 2, axis=0)) < delta])) 54 | return density / pop.shape[1] 55 | 56 | # 激励度算子:计算激励度:计算公式和ppt上的对应 57 | def calc_simulation(self, simulation, density): 58 | return (self.alpha * simulation - self.beta * density) 59 | 60 | # 变异,随着代数增加变异范围逐渐减小 61 | # 变异算子时免疫算法中产生有潜力的新抗体、实现区域搜索的重要算子,它对算法的性能有很大的影响 62 | # 变异算子也和算子的编码方式相关,实数编码的算法和离散编码的算法采用不同的变异算子:具体的可以看ppt 63 | def mutate(self, x, gen, mutata_rate, dim, *limit): 64 | # 这个例子中用的是实数编码变异算子 65 | for i in range(dim): 66 | if np.random.rand() <= mutata_rate: 67 | x[i] += (np.random.rand() - 0.5) * (limit[i][1] - limit[i][0]) / (gen + 1) # 加上随机数产生变异 68 | if (x[i] > limit[i][1]) or (x[i] < limit[i][0]): # 边界检测:边界保护 69 | x[i] = np.random.rand() * (limit[i][1] - limit[i][0]) + limit[i][0] 70 | 71 | def run(self): 72 | # 初始化抗体种群 73 | pop = self.init_pop(self.dim, self.pop_size, self.limit_x, self.limit_y) 74 | # print("初始化抗体种群:", pop) # shape:10行2列 75 | # 初始化激励度,初始时用适应度函数表示,也称为亲和度计算 76 | init_simulation = self.func(pop[0, :], pop[1, :]) 77 | # print("初始化激励度:", init_simulation) # shape 10行1列 78 | # 初始化抗体浓度 79 | density = self.calc_density(pop, self.delta) 80 | # print("初始化抗体浓度:", density) # shape 10行1列 81 | # 计算初始抗体种群的激励度:抗体激励度是对抗体质量的最终评价结果,需要综合考虑抗体亲和度和抗体浓度 82 | simulation = self.calc_simulation(init_simulation, density) 83 | # print("计算初始抗体种群的激励度:", simulation) 84 | index = np.argsort(-simulation) 85 | # np.argsort()将矩阵a按照axis排序,并返回排序后的下标 86 | # print("对初始抗体种群的激励度进行排序后的下标:", index) 87 | pop = pop[:, index] 88 | new_pop = pop.copy() # 浅拷贝 89 | # print("排序后的新的抗体种群:", new_pop) 90 | simulation = simulation[index] 91 | # print("排序后的激励度,与排序后的新的抗体种群对应:", simulation) 92 | # 免疫循环 93 | for gen in range(self.G): 94 | 95 | best_a = np.zeros([self.dim, int(self.pop_size / 2)]) # 用于保留每次克隆后亲和度最高的个体 96 | best_a_simulation = np.zeros([int(self.pop_size / 2), ]) # 保存激励度 97 | 98 | # 免疫选择算子:根据抗体的激励度确定选择哪些抗体进入克隆选择操作,这一步就是进行个体选择的 99 | # 在抗体种群中激励度高的抗体具有更好的质量,更有可能被选中进行克隆操作,在搜索空间中更有搜索价值 100 | # 选出激励度前50%的个体进行免疫 101 | for i in range(int(self.pop_size / 2)): 102 | a = new_pop[:, i].reshape([2, 1]) 103 | # print("免疫选择的结果:", a) # 此时取得是new_pop 的前50%个个体,在循环内部,a是一个个体,即5行两列 104 | # 克隆算子:将免疫选择算子选中的抗体个体进行复制 105 | b = np.tile(a, (1, self.colone_num)) # 克隆10份 106 | # print("克隆结果b", b) # 107 | # 变异算子:变异算子对克隆算子得到的抗体克隆结果进行变异操作 108 | bianyi_jieguo = [] 109 | for j in range(self.colone_num): # 将会产生10个变异体 110 | self.mutate(a, gen, self.mutate_rate, self.dim, self.limit_x, self.limit_y) 111 | bianyi_jieguo.append(a) 112 | # print("变异结果:", bianyi_jieguo) 113 | b[:, 0] = pop[:, i] # 保留克隆源个体,里面是原个体 114 | # print("保留克隆源个体,里面是原个体", b[:, 0]) 115 | # 保留亲和度最高的个体 116 | b_simulation = self.func(b[0, :], b[1, :]) 117 | index = np.argsort(-b_simulation) 118 | # print("保留亲和度最高的个体:", b_simulation) 119 | # print("index", index) [0,1,2,3,4,5,6,7,8,9] 120 | # 最佳个体亲和度 121 | best_a_simulation = b_simulation[index][0] 122 | # 最佳个体 123 | best_a[:, i] = b[:, index][:, 0] # 5行2列 124 | # print("最佳个体亲和度:", best_a_simulation) 125 | # print("最佳个体:", best_a[:]) 126 | 127 | # 计算免疫种群的激励度 128 | a_density = self.calc_density(best_a, self.delta) 129 | best_a_simulation = self.calc_simulation(best_a_simulation, a_density) 130 | 131 | # 种群刷新:种群刷新算子用于对种群中激励度较低的抗体进行刷新,从抗体种群中产出激励度低的个体,并以随机生成的新抗体代替 132 | new_a = self.init_pop(2, int(self.pop_size / 2), self.limit_x, self.limit_y) 133 | 134 | # 新生种群激励度 135 | new_a_simulation = self.func(new_a[0, :], new_a[1, :]) 136 | new_a_density = self.calc_density(new_a, self.delta) 137 | new_a_simulation = self.calc_simulation(new_a_simulation, new_a_density) 138 | 139 | # 免疫种群与新生种群合并 140 | pop = np.hstack([best_a, new_a]) 141 | simulation = np.hstack([best_a_simulation, new_a_simulation]) 142 | index = np.argsort(-simulation) 143 | pop = pop[:, index] 144 | simulation = simulation[index] 145 | new_pop = pop.copy() 146 | # 新建一个画布 147 | figure = plt.figure(figsize=(10, 8), dpi=80) 148 | # 新建一个3d绘图对象 149 | ax = Axes3D(figure) 150 | # 定义x,y 轴名称 151 | plt.xlabel("x") 152 | plt.ylabel("y") 153 | for i in range(int(self.pop_size / 2)): 154 | ax.scatter(pop[0, i], pop[1, i], self.func(pop[0, i], pop[1, i]), color='red') 155 | print('最优解:', 'x = ', pop[0, i], 'y = ', pop[1, i], end='\n') 156 | print('结果:', 'z = ', self.func(pop[0, i], pop[1, i])) 157 | x = np.arange(self.limit_x[0], self.limit_x[1], (self.limit_x[1] - self.limit_x[0]) / 50) 158 | y = np.arange(self.limit_y[0], self.limit_y[1], (self.limit_y[1] - self.limit_y[0]) / 50) 159 | x, y = np.meshgrid(x, y) 160 | z = self.func(x, y) 161 | max_z = np.max(z) 162 | print("max_z:", max_z) 163 | ax.plot_surface(x, y, z, rstride=1, cstride=1, color='green', alpha=0.5) 164 | plt.show() 165 | 166 | 167 | if __name__ == "__main__": 168 | ia = IA() 169 | ia.run() 170 | -------------------------------------------------------------------------------- /布谷鸟搜索算法.py: -------------------------------------------------------------------------------- 1 | from random import uniform 2 | from random import randint 3 | import math 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | 7 | ''' 8 | 根据levy飞行计算新的巢穴位置 9 | ''' 10 | 11 | 12 | def GetNewNestViaLevy(Xt, Xbest, Lb, Ub, lamuda): 13 | beta = 1.5 14 | sigma_u = (math.gamma(1 + beta) * math.sin(math.pi * beta / 2) / ( 15 | math.gamma((1 + beta) / 2) * beta * (2 ** ((beta - 1) / 2)))) ** (1 / beta) 16 | sigma_v = 1 17 | for i in range(Xt.shape[0]): 18 | s = Xt[i, :] 19 | u = np.random.normal(0, sigma_u, 1) 20 | v = np.random.normal(0, sigma_v, 1) 21 | Ls = u / ((abs(v)) ** (1 / beta)) 22 | stepsize = lamuda * Ls * (s - Xbest) # lamuda的设置关系到点的活力程度 方向是由最佳位置确定的 有点类似PSO算法 但是步长不一样 23 | s = s + stepsize * np.random.randn(1, len(s)) # 产生满足正态分布的序列 24 | Xt[i, :] = s 25 | Xt[i, :] = simplebounds(s, Lb, Ub) 26 | return Xt 27 | 28 | 29 | ''' 30 | 按pa抛弃部分巢穴 31 | ''' 32 | 33 | 34 | def empty_nests(nest, Lb, Ub, pa): 35 | n = nest.shape[0] 36 | nest1 = nest.copy() 37 | nest2 = nest.copy() 38 | rand_m = pa - np.random.rand(n, nest.shape[1]) 39 | rand_m = np.heaviside(rand_m, 0) 40 | np.random.shuffle(nest1) 41 | np.random.shuffle(nest2) 42 | # stepsize = np.random.rand(1,1) * (nest1 - nest) 43 | stepsize = np.random.rand(1, 1) * (nest1 - nest2) 44 | new_nest = nest + stepsize * rand_m 45 | nest = simplebounds(new_nest, Lb, Ub) 46 | return nest 47 | 48 | 49 | ''' 50 | 获得当前最优解 51 | ''' 52 | 53 | 54 | def get_best_nest(nest, newnest, Nbest, nest_best): 55 | # get_best_nest(nest, nest, Nbest, nest_best) 56 | fitall = 0 57 | for i in range(nest.shape[0]): 58 | temp1 = fitness(nest[i, :]) 59 | temp2 = fitness(newnest[i, :]) 60 | if temp1 > temp2: 61 | nest[i, :] = newnest[i, :] 62 | if temp2 < Nbest: 63 | Nbest = temp2 64 | nest_best = nest[i, :] 65 | fitall = fitall + temp2 66 | else: 67 | fitall = fitall + temp1 68 | meanfit = fitall / nest.shape[0] 69 | return nest, Nbest, nest_best, meanfit 70 | 71 | 72 | ''' 73 | 进行适应度计算 74 | ''' 75 | 76 | 77 | def fitness(nest_n): 78 | X = nest_n[0] 79 | Y = nest_n[1] 80 | # rastrigin函数 81 | A = 10 82 | Z = 2 * A + X ** 2 - A * np.cos(2 * np.pi * X) + Y ** 2 - A * np.cos(2 * np.pi * Y) 83 | 84 | return Z 85 | 86 | 87 | ''' 88 | 进行全部适应度计算 89 | ''' 90 | 91 | 92 | def fit_function(X, Y): 93 | # rastrigin函数 94 | A = 10 95 | Z = 2 * A + X ** 2 - A * np.cos(2 * np.pi * X) + Y ** 2 - A * np.cos(2 * np.pi * Y) 96 | return Z 97 | 98 | 99 | ''' 100 | 约束迭代结果 101 | ''' 102 | 103 | 104 | def simplebounds(s, Lb, Ub): 105 | for i in range(s.shape[0]): 106 | for j in range(s.shape[1]): 107 | if s[i][j] < Lb[j]: 108 | s[i][j] = Lb[j] 109 | if s[i][j] > Ub[j]: 110 | s[i][j] = Ub[j] 111 | return s 112 | 113 | 114 | def Get_CS(lamuda=1, pa=0.25): 115 | Lb = [-5, -5] # 下界 116 | Ub = [5, 5] # 上界 117 | population_size = 20 118 | dim = 2 119 | nest = np.random.uniform(Lb[0], Ub[0], (population_size, dim)) # 初始化位置 120 | nest_best = nest[0, :] 121 | Nbest = fitness(nest_best) 122 | nest, Nbest, nest_best, fitmean = get_best_nest(nest, nest, Nbest, nest_best) 123 | for i in range(30): 124 | nest_c = nest.copy() 125 | newnest = GetNewNestViaLevy(nest_c, nest_best, Lb, Ub, lamuda) # 根据莱维飞行产生新的位置 126 | 127 | nest, Nbest, nest_best, fitmean = get_best_nest(nest, newnest, Nbest, nest_best) # 判断新的位置优劣进行替换 128 | 129 | nest_e = nest.copy() 130 | newnest = empty_nests(nest_e, Lb, Ub, pa) # 丢弃部分巢穴 131 | 132 | nest, Nbest, nest_best, fitmean = get_best_nest(nest, newnest, Nbest, nest_best) # 再次判断新的位置优劣进行替换 133 | 134 | print("最优解的适应度函数值", Nbest) 135 | return Nbest 136 | 137 | 138 | Get_CS() -------------------------------------------------------------------------------- /模拟退火算法.py: -------------------------------------------------------------------------------- 1 | import math 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | from random import random 5 | 6 | # 首先要明确的是 模拟退火算法是一个局部搜索算法,它一般结合全局搜索算法使用,用来打辅助 7 | """ 8 | 模拟退火算法步骤: 9 | (1)初始化:初始温度T0;终止条件 T<1 ; 退火速率alpha(0.8-0.99);每个温度下的迭代次数L 10 | (2)在给定温度下,产生新解,计算增量,按照Metropolis准则判断是否接受新解,如果接受,用新解代替旧解,同时修正目标函数 11 | (3)降低温度T,回到第二步 12 | (4)如果满足终止条件则输出当前解作为最优解,结束程序。否则,回到第(2)步 13 | 14 | """ 15 | 16 | 17 | # 首先定义目标函数 18 | def func(x, y): 19 | res = 4 * x ** 2 - 2.1 * x ** 4 + x ** 6 / 3 + x * y - 4 * y ** 2 + 4 * y ** 4 20 | return res 21 | 22 | 23 | class SA: 24 | def __init__(self, func, iter=100, T0=100, Tf=0.01, alpha=0.99): 25 | self.func = func # 目标函数 26 | self.iter = iter # 迭代次数 27 | self.alpha = alpha # 退火速率 28 | self.T0 = T0 # 初始温度 29 | self.Tf = Tf # 终止温度 30 | self.T = T0 # 当前温度 31 | self.x = [np.random.uniform(-5, 5) for i in range(iter)] # 随机生成100个x1的值 32 | self.y = [np.random.uniform(-5, 5) for i in range(iter)] # 随机生成100个x2的值 33 | self.most_best = [] 34 | self.history = {'f': [], 'T': []} 35 | 36 | def generate_new(self, x, y): # 扰动产生新解的过程:通常选择由当前新解经过简单地变换即可产生新解的方法 37 | while True: # 这里用的是随机扰动,感觉这个产生新解的方法不是很好,因为新解和旧解之间的差异很大 38 | # print("旧解:", x) 39 | x_new = x + self.T * (random() - random()) 40 | # print("新解:", x_new) 41 | y_new = y + self.T * (random() - random()) 42 | if (-5 <= x_new <= 5) & (-5 <= y_new <= 5): 43 | break 44 | return x_new, y_new 45 | 46 | def Metrospolis(self, f, f_new): 47 | if f_new <= f: 48 | return 1 # 完全接受 49 | else: 50 | p = math.exp((f - f_new) / self.T) 51 | if random() < p: 52 | return 1 53 | else: 54 | return 0 55 | 56 | def best(self): 57 | f_list = [] # f_list数组保存每次迭代之后的值 58 | for i in range(self.iter): 59 | f = self.func(self.x[i], self.y[i]) # 计算每一代的适应度值 60 | f_list.append(f) 61 | f_best = min(f_list) # 找出100代中适应度值最小的那个值,就是f_best 62 | idx = f_list.index(f_best) # 63 | return f_best, idx # f_best,idx分别是在该温度下,迭代L次之后目标函数的最优解和最优解的下标 64 | 65 | def run(self): 66 | # 外循环迭代,当前温度小于终止温度的阈值 67 | while self.T > self.Tf: 68 | # 内循环迭代100次 69 | for i in range(self.iter): 70 | #print("第", i, "代") 71 | # 计算解的适应度值 72 | f = self.func(self.x[i], self.y[i]) 73 | # 给定温度下,产生新解 74 | x_new, y_new = self.generate_new(self.x[i], self.y[i]) 75 | # 计算新解的适应度值 76 | f_new = self.func(x_new, y_new) 77 | # 依据Metropolis原则,进行新解的接受与否判断 78 | if self.Metrospolis(f, f_new): # 如果判断是接受新解,就新解代替旧解 79 | self.x[i] = x_new 80 | self.y[i] = y_new 81 | #print(self.x) 82 | # 记录在T温度下的最优解(迭代L次记录在该温度下的最优解) 83 | ft, _ = self.best() 84 | self.history['f'].append(ft) 85 | self.history['T'].append(self.T) 86 | # 温度按照一定的比例下降(冷却) 87 | self.T = self.T * self.alpha 88 | # 得到最优解 89 | f_best, idx = self.best() 90 | print(f"F={f_best},x={self.x[idx]},y={self.y[idx]}") 91 | 92 | 93 | sa = SA(func) 94 | sa.run() 95 | plt.plot(sa.history['T'], sa.history['f']) 96 | plt.title('SA') 97 | plt.xlabel('T') 98 | plt.ylabel('f') 99 | plt.gca().invert_xaxis() 100 | plt.show() 101 | -------------------------------------------------------------------------------- /禁忌搜索算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import random as rd 4 | 5 | """ 6 | 禁忌搜索算法步骤: 7 | (1)初始化参数: 8 | 产生初始解s,并将禁忌表置为空 9 | (2)根据邻域动作产生邻域解N(s),根据适应度值选出候选解。 10 | (3)判断候选解是否满足特赦准则, 11 | (3.1):如果满足,就将满足特赦准则的解作为当前解,用其对应的对象替换最早进入禁忌表中的对象,更新最优解 12 | (3.2):如果不满足特赦准则,就接着判断候选解是否在禁忌表中: 13 | (3.2.1) 有部分在禁忌表中 14 | (3.2.1.1)在候选解中存在比最优方案还好的方案,那就找到候选集中最最优的那个解: 15 | # 如果优此时的解于当前最好解,那么就不考虑其是否被禁忌,用这个最好的候选解来更新当前最好 16 | # 如果不优于当前最好解,就从所有候选解中选出不在禁忌状态下的最好解作为新的当前解,然后将对应对象加入禁忌表 17 | (3.2.1.2)在候选解中不存在比最优方案好的方案, 18 | 记录不在禁忌表中的候选解,从候选解集合中找到最优的那个解,然后与当前最优解比较,看是否更新当前解与最优解 19 | (3.2.2) 候选解都不在禁忌表中,那么就将非禁忌的最佳候选解作为当前解,用该解对应的对象替换最早进入禁忌表中的对象 20 | (4)满足终止准则,就输出最优解,如果不满足重复(2)(3)步 21 | """ 22 | 23 | 24 | # 自变量约束条件 25 | MIN_VAL = [-5.0, -5.0] 26 | MAX_VAL = [5.0, 5.0] 27 | 28 | 29 | # Class definition 30 | class TS(): 31 | def __init__(self, vcount=2, ccount=20, tabuL=25, iters=200, tabu_objs=10): 32 | self.vcount = vcount # 自变量的个数 33 | self.ccount = ccount # 候选解的个数 34 | self.iters = iters # 最大迭代次数 35 | self.tabu_objs = tabu_objs # 禁忌对象 36 | self.tabu_list = [None] * self.tabu_objs # 禁忌表,存放禁忌对象,禁忌表长度10 37 | self.tabu_len = tabuL # 禁忌长度 38 | self.tabu_len_list = np.array([0] * self.tabu_objs) # 禁忌长度列表,对应于禁忌列表。 39 | self.cur_solu = np.array([0.0] * self.vcount) # 当前解 40 | self.best_solu = np.array([0.0] * self.vcount) # 最优解 41 | self.trace = [] # 记录最优解的路径 42 | 43 | def valuate(self, x): 44 | # 目标/评价函数 45 | value = 5 * np.cos(x[0] * x[1]) + x[0] * x[1] + x[1] ** 3 46 | return value 47 | 48 | # 更新禁忌表,这一部分是很重要的,对理解代码有着很核心的作用 49 | # 禁忌表有两种操作:添加禁忌元素和删除禁忌元素 50 | def update_Tabu(self, mode, index=None, solu=None): 51 | indices = [] # 存储禁忌对象的禁忌期限为0的对象的索引 52 | # 更新禁忌对象的禁忌期限 53 | for i in range(len(self.tabu_len_list)): # 长度为10, 54 | if self.tabu_len_list[i] != 0: # 每进行一次禁忌表更新操作,对应的禁忌对象的使用期限就-1,一直到0 55 | self.tabu_len_list[i] -= 1 56 | print("tabu_list", self.tabu_list) 57 | print("tabu_len_list", self.tabu_len_list) 58 | 59 | # 释放紧急对象 60 | if mode == 'release': 61 | self.sequence_Tabu(index) 62 | # 向禁忌表中添加禁忌对象,添加到禁忌表的 63 | elif mode == 'add': 64 | tabuObj = self.valuate(solu) # 禁忌表对象是解的valuate值, 65 | if self.tabu_list[0] == None: 66 | #print("从后往前插入") 67 | self.sequence_Tabu(0) 68 | self.tabu_list[len(self.tabu_list) - 1] = tabuObj 69 | # print("self.tabu_list[9]", self.tabu_list[9]) 70 | self.tabu_len_list[len(self.tabu_list) - 1] = self.tabu_len 71 | 72 | for i in range(len(self.tabu_len_list)): 73 | if self.tabu_len_list[i] == 0: # 如果禁忌对象的使用期限为0 74 | # 就将此禁忌对象的索引加到indices中 75 | indices.append(i) 76 | print("禁忌对象的禁忌期限为0的对象的索引:", indices) 77 | if len(indices) == 1: # 如果此时indices中只有一个禁忌对象,直接从禁忌表中删除即可 78 | self.sequence_Tabu(indices[0]) 79 | elif len(indices) > 1: # 如果此时indices中有多个禁忌对象 80 | # Part 1 81 | maxindex = max(indices) # 找出索引值最大的 82 | print("索引值最大的", maxindex) 83 | self.sequence_Tabu(maxindex) # 然后从禁忌表中删除maxindex 84 | print("从禁忌表中删除maxindex:", self.tabu_list) 85 | # Part 2 86 | for i in indices: # 遍历indices,里面存放的是禁忌期限为0的索引 87 | if i != max(indices): # 如果禁忌对象不等于最大的那个禁忌对象 88 | self.tabu_list[i] = None # 可以直接设置禁忌表中此禁忌对象为None 89 | self.tabu_len_list[i] = 0 # 同时将此禁忌对象的禁忌期限设置为0 90 | objs = [] 91 | objs1 = [] 92 | for obj in self.tabu_list[:maxindex]: 93 | if obj != None: 94 | objs.append(obj) # objs里存放的是禁忌表中不为None的禁忌对象 95 | for obj in self.tabu_len_list[:maxindex]: 96 | if obj != 0: 97 | objs1.append(obj) # objs1里面存放的是禁忌表期限表中不为0的禁忌对象的使用期限 98 | if objs != []: # 如果禁忌表中还存在禁忌对象,禁忌对象在禁忌表中往前移动一位 99 | for i in range(len(objs)): 100 | self.tabu_list[maxindex - i - 1] = objs[i] 101 | self.tabu_len_list[maxindex - i - 1] = objs1[i] 102 | for i in range(maxindex - len(objs)): 103 | self.tabu_list[i] = None 104 | self.tabu_len_list[i] = 0 105 | else: 106 | for i in range(maxindex): 107 | self.tabu_list[i] = None 108 | self.tabu_len_list[i] = 0 109 | print("此时禁忌表的样子:", self.tabu_list) 110 | print("此时禁忌表期限表的样子:", self.tabu_len_list) 111 | 112 | def sequence_Tabu(self, index): 113 | # 从禁忌表中释放禁忌对象 114 | if index != len(self.tabu_list) - 1: 115 | for i in range(len(self.tabu_list) - 1 - index): 116 | self.tabu_list[index + i] = self.tabu_list[index + i + 1] # 使要删除的元素在禁忌表的最后一位 117 | self.tabu_len_list[index + i] = self.tabu_len_list[index + i + 1] 118 | self.tabu_list[len(self.tabu_list) - 1] = None # 将禁忌表的最后一位置为None,表示删除 119 | 120 | self.tabu_len_list[len(self.tabu_list) - 1] = 0 121 | #print("后移:", self.tabu_list) 122 | #print("后移:", self.tabu_len_list) 123 | 124 | def run(self): 125 | #(1)初始化参数:产生初始解s --> cur_solu ,并将禁忌表置为空 126 | for i in range(self.vcount): 127 | # 产生初始解 128 | self.cur_solu[i] = rd.uniform(-5, 5) 129 | # 设置最优解 130 | self.best_solu[i] = self.cur_solu[i] 131 | print("初始解:", self.cur_solu) # 初始解: [1.30533424 0.72105434] 132 | # 更新禁忌列表和禁忌对象的使用期限。 133 | self.update_Tabu('add', solu=self.cur_solu) 134 | counter = 0 # 记录迭代次数 135 | while counter < self.iters: # 进入迭代循环 136 | counter += 1 # 当完成一次迭代,就将次数加1 137 | 138 | # (2)根据邻域动作产生邻域解N(s) --> candi_solu 139 | candi_solu = np.zeros((self.ccount, self.vcount)) # 候选解集合:用来存放候选解 140 | # 从当前解的邻域内选出一些候选解,加入候选解集合中 141 | for i in range(self.ccount): 142 | for j in range(self.vcount): 143 | candi_solu[i, j] = self.cur_solu[j] + rd.uniform(-1, 1) # 邻域动作 144 | # print("候选解集合:", candi_solu) # 20行2列 145 | # 越界保护(几乎所有的算法都要有越界保护,否则有些更新函数会使变量的值跑出约束条件的范围) 146 | for i in range(self.vcount): 147 | for j in range(self.ccount): 148 | if candi_solu[j, i] > MAX_VAL[i]: 149 | candi_solu[j, i] = MAX_VAL[i] 150 | elif candi_solu[j, i] < MIN_VAL[i]: 151 | candi_solu[j, i] = MIN_VAL[i] 152 | 153 | # A sign of all solutions kept in tabu list. 154 | # 候选解集合中的候选解是否全部被禁忌,如果为True,表示满足特赦准则 155 | isAll = False 156 | # 候选解集合中的候选解是否只有部分在禁忌表中时,如果为True,表示只有部分在禁忌表中 157 | isPart = False 158 | count = [0] * self.ccount 159 | for i in range(self.ccount): # 遍历候选解集合中的每一个候选解 160 | for k in range(len(self.tabu_list)): # 遍历禁忌表 161 | # 判断候选解的valuate值是否与禁忌表中某禁忌对象相等 162 | if self.valuate(candi_solu[i]) == self.tabu_list[k]: # 如果相等,表示此候选解被禁 163 | count[i] = 1 # 将此候选解的标记置为1,表示被禁 164 | temp = 0 165 | for i in count: 166 | if i == 1: 167 | temp += 1 168 | if temp == self.ccount: 169 | isAll = True 170 | elif temp < self.ccount and temp > 0: 171 | isPart = True 172 | 173 | if isAll == True: 174 | ############################################ 175 | # Part1 :先来看第一种情况:所有候选解都在禁忌表中,此时满足特赦准则: 176 | # 将满足特赦准则的解作为当前解,用其对应的对象替换最早进入禁忌表中的对象,更新最优解 # 177 | ############################################ 178 | temp_tabu_list = [] # 禁忌缓存表 179 | for tabuObj in self.tabu_list: 180 | if tabuObj != None: 181 | temp_tabu_list.append(tabuObj) # 将禁忌表中的元素移到禁忌缓存表中 182 | # 从禁忌列表中获取最小值的索引 183 | index = np.argmin(np.array(temp_tabu_list)) 184 | # print("从禁忌列表中获取最小值的索引", index) 185 | # 临时解 186 | temp_solu = np.array([0.0] * self.vcount) 187 | for solu in candi_solu: # 遍历候选解集合 188 | # 如果候选解的评级函数和禁忌表中最小值相等,表示是合中的最佳候选解 189 | if self.valuate(solu) == self.tabu_list[index]: 190 | temp_solu = solu # 将此时的候选解赋值给临时解 191 | # 将该候选解作为当前解 192 | self.cur_solu = temp_solu 193 | # Update the best solution according to the valuate function and requirements. 194 | # 更新最优解:即将当前解的评价函数和最优解的比较,如果当前解更优,就更新最优解 195 | if self.valuate(self.cur_solu) < self.valuate(self.best_solu): 196 | self.best_solu = self.cur_solu 197 | # Update the tabu list and the tenure of tabu object. 198 | # 更新禁忌表:从禁忌表中将此解对应的禁忌对象删除。 199 | self.update_Tabu('release', index=index) 200 | 201 | elif isPart == True: 202 | ################################################## 203 | # Part2 : 候选解有一部分在禁忌表中. # 204 | ################################################## 205 | isExistbest = False 206 | temp_bsolu = [] 207 | bsolu = np.array([0.0] * self.vcount) 208 | for solu in candi_solu: 209 | if self.valuate(solu) < self.valuate(self.best_solu): 210 | isExistbest = True 211 | temp_bsolu.append(solu) 212 | if isExistbest == True: 213 | ################################################################### 214 | # Part2.1 : 在候选解决方案中存在最佳解决方案。 # 215 | # 有些在禁忌列表中 # 216 | ################################################################### 217 | isInTabu = False 218 | index = 0 219 | # 如果只有一个候选解是优于当前最优解的,那么直接将这个候选解赋值给bsolu 220 | if len(temp_bsolu) == 1: 221 | bsolu = temp_bsolu[0] 222 | # 如果存在多个候选解是优于当前最优解的,那就找出这些候选解中最最优的那一个,赋值给bsolu 223 | elif len(temp_bsolu) != 1 and len(temp_bsolu) != 0: 224 | bsolu = temp_bsolu[0] 225 | for solu in temp_bsolu[1:]: 226 | if self.valuate(solu) < self.valuate(bsolu): 227 | bsolu = solu 228 | # 上面的代码就是 在候选解集合中找到最优的那个解 229 | # 已经不满足特赦准则了,那么就要判断候选解是否被禁 230 | for i in range(len(self.tabu_list)): # 遍历禁忌表,看是候选解是否在禁忌表中 231 | if self.valuate(bsolu) == self.tabu_list[i]: # 如果在 232 | isInTabu = True 233 | index = i # 记录此解在禁忌表中的位置 234 | 235 | self.cur_solu = bsolu 236 | # 如果优于当前最好解,那么就不考虑其是否被禁忌,用这个最好的候选解来更新当前最好 237 | 238 | if self.valuate(bsolu) < self.valuate(self.best_solu): 239 | self.best_solu = bsolu 240 | # 如果不优于当前最好解,就从所有候选解中选出不在禁忌状态下的最好解作为新的当前解,然后将对应对象加入禁忌表 241 | if isInTabu == True: 242 | # 更新禁忌表和禁忌长度 243 | self.update_Tabu('release', index=index) 244 | else: 245 | # 如果不优于当前最好解,就从所有候选解中选出不在禁忌状态下的最好解作为新的当前解,然后将对应对象加入禁忌表 246 | index = len(self.tabu_list) - 1 247 | # Update the tabu list and the tenure of tabu object. 248 | self.update_Tabu(index, 'add', solu=self.cur_solu) 249 | else: 250 | ################################################################# 251 | # Part2.2 : 在候选解决方案中没有一个是最好的解决方案 # 252 | # None solutions exist in tabu list. # 253 | ################################################################# 254 | notInTabu = [] # 记录不在禁忌表中的候选解 255 | for solu in candi_solu: 256 | count = 0 257 | for i in range(len(self.tabu_list)): 258 | if self.valuate(solu) != self.tabu_list[i]: 259 | count += 1 260 | if count == len(self.tabu_list): 261 | notInTabu.append(solu) 262 | # 263 | temp_solu = notInTabu[0] 264 | if len(notInTabu) != 1: # 有多个候选解,选出最优的那个候选解赋值给temp_solu 265 | for solu in notInTabu[1:]: 266 | if self.valuate(solu) < self.valuate(temp_solu): 267 | temp_solu = solu 268 | # 根据适应度值选择是否更新当前解,如果候选解的值比当前解更优就更新当前解 269 | if self.valuate(temp_solu) < self.valuate(self.cur_solu): 270 | self.cur_solu = temp_solu # 更新当前解 271 | # 更新禁忌表和禁忌长度 272 | self.update_Tabu('add', index=len(self.tabu_list) - 1, solu=self.cur_solu) 273 | # 根据适应度值更新最优解 274 | if self.valuate(self.cur_solu) < self.valuate(self.best_solu): 275 | self.best_solu = self.cur_solu 276 | 277 | else: 278 | ############################################# 279 | # Part3 : 候选解都不在禁忌表中,即都没有被禁 # 280 | ############################################# 281 | bcandi_solu = candi_solu[0] 282 | for solu in candi_solu[1:]: 283 | if self.valuate(solu) < self.valuate(bcandi_solu): 284 | bcandi_solu = solu 285 | # Update the current solution according to the valuate function and requirements. 286 | if self.valuate(bcandi_solu) < self.valuate(self.cur_solu): 287 | self.cur_solu = bcandi_solu 288 | # Update the tabu list and the tenure of tabu object. 289 | self.update_Tabu('add', index=len(self.tabu_list) - 1, solu=self.cur_solu) 290 | # Update the best solution according to the valuate function and requirements. 291 | if self.valuate(self.cur_solu) < self.valuate(self.best_solu): 292 | self.best_solu = self.cur_solu 293 | 294 | # Add the best solution to the trace list 295 | self.trace.append(self.valuate(self.best_solu)) 296 | # print(self.trace) 297 | 298 | 299 | if __name__ == "__main__": 300 | ts = TS(iters=200) 301 | ts.run() 302 | print('最优解:', ts.best_solu) 303 | print('最小值', ts.valuate(ts.best_solu)) 304 | plt.plot(ts.trace, 'r') 305 | title = 'TS: ' + str(ts.valuate(ts.best_solu)) 306 | plt.title(title) 307 | plt.show() 308 | -------------------------------------------------------------------------------- /粒子群算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | """ 5 | 粒子群算法实现步骤: 6 | (1)初始化: 7 | 初始化参数:学习因子c1,c2:一般取2; 惯性权重w:一般取0.9-1.2; 种群数量N:50-1000;迭代次数:100-4000;空间维数:自变量的个数;位置限制:自变量的取值范围;速度限制:可以控制在0-1之间。 8 | 初始化粒子群:包括粒子群的初始位置和速度 9 | 根据初始化得到的粒子群计算p_best,g_best 10 | (2)更新粒子位置和粒子的速度 11 | (3)计算每个粒子的适应度值 12 | (4)根据适应度值更新p_best(个体最佳历史位置),g_best(全局最佳历史位置) 13 | (5)判断是否满足结束条件,满足输出最优解,不满足转到第(2) 14 | """ 15 | 16 | 17 | class PSO(object): 18 | def __init__(self, population_size, max_steps): 19 | self.x = None 20 | self.w = 0.6 # 惯性权重 21 | self.c1 = self.c2 = 2 # 学习因子 22 | self.population_size = population_size # 粒子群数量 23 | self.dim = 4 # 搜索空间的维度 24 | self.max_steps = max_steps # 迭代次数 25 | self.bound = [] # 自变量的约束范围 26 | self.bound.append([1, 1, 1, 1]) 27 | self.x = np.zeros((self.population_size, self.dim)) 28 | self.bound.append([30, 30, 30, 30]) # 解空间范围 29 | for i in range(self.population_size): # 对于每一只蚂蚁来说都会有一个潜在解 30 | for j in range(self.dim): # 取出每一个变量,产生一个在[var_num_min,var_num_max]范围内的随机数 31 | self.x[i][j] = np.random.uniform(self.bound[0][j], self.bound[1][j]) 32 | self.v = np.random.rand(self.population_size, self.dim) # 初始化粒子群速度 33 | # print("v", self.v) # population行4列, 34 | # fitness = self.calculate_fitness(self.x) 35 | self.Fitness = [] 36 | for i in range(self.population_size): 37 | fitness = self.calculate_fitness(self.x[i]) 38 | self.Fitness.append(fitness) 39 | self.p_best = self.x # 个体的最优位置 40 | print("个体最优位置:", self.p_best) 41 | self.g_best = self.x[np.argmax(self.Fitness)] # 全局最优位置 42 | print("全局最优位置:", self.g_best) 43 | self.individual_best_fitness = self.Fitness # 个体的最优适应度 44 | print("个体最优适应度:", self.individual_best_fitness) 45 | self.global_best_fitness = np.max(self.Fitness) # 全局最佳适应度 46 | print("全局最优适应度:", self.global_best_fitness) 47 | 48 | def calculate_fitness(self, x): 49 | x1 = x[0] 50 | x2 = x[1] 51 | x3 = x[2] 52 | x4 = x[3] 53 | y = x1 ** 2 + x2 ** 2 + x3 ** 3 + x4 ** 4 54 | # print("fitness:", y) 55 | return y 56 | 57 | def evolve(self): # evolve进化的意思 58 | fig = plt.figure() 59 | for step in range(self.max_steps): 60 | r1 = np.random.rand(self.population_size, self.dim) # 返回一个或者一组0-1之间的随机数或者随机数组 61 | r2 = np.random.rand(self.population_size, self.dim) 62 | # 更新速度和权重 63 | # 64 | self.v = self.w * self.v + self.c1 * r1 * (self.p_best - self.x) + self.c2 * r2 * (self.g_best - self.x) 65 | self.x = self.v + self.x 66 | for i in range(self.population_size): 67 | for j in range(self.dim): 68 | if self.v[i][j] < self.bound[0][j]: 69 | self.v[i][j] = self.bound[0][j] 70 | if self.x[i][j] > self.bound[1][j]: 71 | self.x[i][j] = self.bound[1][j] 72 | 73 | for i in range(self.population_size): # 对于每一个粒子. 74 | fitness = self.calculate_fitness(self.x[i]) # 新的粒子群的适应度,100行1列 75 | # 需要更新的个体 76 | if fitness > self.individual_best_fitness[i]: 77 | self.p_best[i] = self.x[i] 78 | self.individual_best_fitness[i] = fitness # ppt中没有说要更新个体历史适应度,但我觉得应该是要更新的,这样收敛的速度会加快 79 | print("用当前位置更新粒子个体的历史最优位置p_best") 80 | print("更改之后的粒子最优位置:", self.p_best[i]) 81 | else: 82 | print("当前个体适应度值 小于 这个个体的历史最优位置的适应度值,不用更新") 83 | if fitness > self.global_best_fitness: 84 | self.g_best = self.x[i] 85 | self.global_best_fitness = fitness 86 | print("个体最优适应度:", self.individual_best_fitness) 87 | print('best fitness : %.5f,mean fitness : %.5f' % (self.global_best_fitness, np.mean(fitness))) 88 | 89 | 90 | pso = PSO(10, 100) 91 | pso.evolve() 92 | 93 | -------------------------------------------------------------------------------- /细菌觅食优化算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random 3 | import copy 4 | import matplotlib.pyplot as plt 5 | import ObjFunction 6 | 7 | 8 | 9 | class BFOIndividual: 10 | 11 | ''' 12 | individual of baterial clony foraging algorithm 13 | ''' 14 | 15 | def __init__(self, vardim, bound): 16 | ''' 17 | vardim: dimension of variables 18 | bound: boundaries of variables 19 | ''' 20 | self.vardim = vardim 21 | self.bound = bound 22 | self.fitness = 0. 23 | self.trials = 0 24 | 25 | def generate(self): 26 | ''' 27 | generate a random chromsome for baterial clony foraging algorithm 28 | ''' 29 | len = self.vardim 30 | rnd = np.random.random(size=len) 31 | self.chrom = np.zeros(len) 32 | for i in range(0, len): 33 | self.chrom[i] = self.bound[0, i] + \ 34 | (self.bound[1, i] - self.bound[0, i]) * rnd[i] 35 | 36 | def calculateFitness(self): 37 | ''' 38 | calculate the fitness of the chromsome 39 | ''' 40 | self.fitness = ObjFunction.GrieFunc( 41 | self.vardim, self.chrom, self.bound) 42 | """ 43 | s1 = 0. 44 | s2 = 1. 45 | for i in range(1, self.vardim + 1): 46 | s1 = s1 + self.chrom[i - 1] ** 2 47 | s2 = s2 * np.cos(self.chrom[i - 1] / np.sqrt(i)) 48 | y = (1. / 4000.) * s1 - s2 + 1 49 | self.fitness = y 50 | """ 51 | 52 | class BacterialForagingOptimization: 53 | 54 | ''' 55 | The class for baterial foraging optimization algorithm 56 | ''' 57 | 58 | def __init__(self, sizepop, vardim, bound, params): 59 | ''' 60 | sizepop: population sizepop 61 | vardim: dimension of variables 62 | bound: boundaries of variables 63 | param: algorithm required parameters, it is a list which is consisting of [Ned, Nre, Nc, Ns, C, ped, d_attract, w_attract, d_repellant, w_repellant] 64 | ''' 65 | self.sizepop = sizepop 66 | self.vardim = vardim 67 | self.bound = bound 68 | self.population = [] 69 | self.bestPopulation = [] 70 | self.accuFitness = np.zeros(self.sizepop) 71 | self.fitness = np.zeros(self.sizepop) 72 | self.params = params 73 | self.trace = np.zeros( 74 | (self.params[0] * self.params[1] * self.params[2], 2)) 75 | 76 | def initialize(self): 77 | ''' 78 | initialize the population 79 | ''' 80 | for i in range(0, self.sizepop): 81 | ind = BFOIndividual(self.vardim, self.bound) 82 | ind.generate() 83 | self.population.append(ind) 84 | 85 | def evaluate(self): 86 | ''' 87 | evaluation of the population fitnesses 88 | ''' 89 | for i in range(0, self.sizepop): 90 | self.population[i].calculateFitness() 91 | self.fitness[i] = self.population[i].fitness 92 | 93 | def sortPopulation(self): 94 | ''' 95 | sort population according descending order 96 | ''' 97 | sortedIdx = np.argsort(self.accuFitness) 98 | newpop = [] 99 | newFitness = np.zeros(self.sizepop) 100 | for i in range(0, self.sizepop): 101 | ind = self.population[sortedIdx[i]] 102 | newpop.append(ind) 103 | self.fitness[i] = ind.fitness 104 | self.population = newpop 105 | 106 | def solve(self): 107 | ''' 108 | evolution process of baterial clony foraging algorithm 109 | ''' 110 | self.t = 0 111 | self.initialize() 112 | self.evaluate() 113 | bestIndex = np.argmin(self.fitness) 114 | self.best = copy.deepcopy(self.population[bestIndex]) 115 | 116 | for i in range(0, self.params[0]): 117 | for j in range(0, self.params[1]): 118 | for k in range(0, self.params[2]): 119 | self.t += 1 120 | self.chemotaxls() 121 | self.evaluate() 122 | best = np.min(self.fitness) 123 | bestIndex = np.argmin(self.fitness) 124 | if best < self.best.fitness: 125 | self.best = copy.deepcopy(self.population[bestIndex]) 126 | self.avefitness = np.mean(self.fitness) 127 | self.trace[self.t - 1, 0] = self.best.fitness 128 | self.trace[self.t - 1, 1] = self.avefitness 129 | print("Generation %d: optimal function value is: %f; average function value is %f" % ( 130 | self.t, self.trace[self.t - 1, 0], self.trace[self.t - 1, 1])) 131 | self.reproduction() 132 | self.eliminationAndDispersal() 133 | 134 | print("Optimal function value is: %f; " % 135 | self.trace[self.t - 1, 0]) 136 | print("Optimal solution is:") 137 | print(self.best.chrom) 138 | self.printResult() 139 | 140 | def chemotaxls(self): 141 | ''' 142 | chemotaxls behavior of baterials 143 | ''' 144 | for i in range(0, self.sizepop): 145 | tmpInd = copy.deepcopy(self.population[i]) 146 | self.fitness[i] += self.communication(tmpInd) 147 | Jlast = self.fitness[i] 148 | rnd = np.random.uniform(low=-1, high=1.0, size=self.vardim) 149 | phi = rnd / np.linalg.norm(rnd) 150 | tmpInd.chrom += self.params[4] * phi 151 | for k in range(0, self.vardim): 152 | if tmpInd.chrom[k] < self.bound[0, k]: 153 | tmpInd.chrom[k] = self.bound[0, k] 154 | if tmpInd.chrom[k] > self.bound[1, k]: 155 | tmpInd.chrom[k] = self.bound[1, k] 156 | tmpInd.calculateFitness() 157 | m = 0 158 | while m < self.params[3]: 159 | if tmpInd.fitness < Jlast: 160 | Jlast = tmpInd.fitness 161 | self.population[i] = copy.deepcopy(tmpInd) 162 | # print m, Jlast 163 | tmpInd.fitness += self.communication(tmpInd) 164 | tmpInd.chrom += self.params[4] * phi 165 | for k in range(0, self.vardim): 166 | if tmpInd.chrom[k] < self.bound[0, k]: 167 | tmpInd.chrom[k] = self.bound[0, k] 168 | if tmpInd.chrom[k] > self.bound[1, k]: 169 | tmpInd.chrom[k] = self.bound[1, k] 170 | tmpInd.calculateFitness() 171 | m += 1 172 | else: 173 | m = self.params[3] 174 | self.fitness[i] = Jlast 175 | self.accuFitness[i] += Jlast 176 | 177 | def communication(self, ind): 178 | ''' 179 | cell to cell communication 180 | ''' 181 | Jcc = 0.0 182 | term1 = 0.0 183 | term2 = 0.0 184 | for j in range(0, self.sizepop): 185 | term = 0.0 186 | for k in range(0, self.vardim): 187 | term += (ind.chrom[k] - 188 | self.population[j].chrom[k]) ** 2 189 | term1 -= self.params[6] * np.exp(-1 * self.params[7] * term) 190 | term2 += self.params[8] * np.exp(-1 * self.params[9] * term) 191 | Jcc = term1 + term2 192 | 193 | return Jcc 194 | 195 | def reproduction(self): 196 | ''' 197 | reproduction of baterials 198 | ''' 199 | self.sortPopulation() 200 | newpop = [] 201 | for i in range(0, self.sizepop // 2): 202 | newpop.append(self.population[i]) 203 | for i in range(self.sizepop // 2, self.sizepop): 204 | self.population[i] = newpop[i - self.sizepop // 2] 205 | 206 | def eliminationAndDispersal(self): 207 | ''' 208 | elimination and dispersal of baterials 209 | ''' 210 | for i in range(0, self.sizepop): 211 | rnd = random.random() 212 | if rnd < self.params[5]: 213 | self.population[i].generate() 214 | 215 | def printResult(self): 216 | ''' 217 | plot the result of the baterial clony foraging algorithm 218 | ''' 219 | x = np.arange(0, self.t) 220 | y1 = self.trace[:, 0] 221 | y2 = self.trace[:, 1] 222 | plt.plot(x, y1, 'r', label='optimal value') 223 | plt.plot(x, y2, 'g', label='average value') 224 | plt.xlabel("Iteration") 225 | plt.ylabel("function value") 226 | plt.title( 227 | "Baterial clony foraging algorithm for function optimization") 228 | plt.legend() 229 | plt.show() 230 | 231 | if __name__ == "__main__": 232 | bound = np.tile([[-600], [600]], 25) 233 | bfo = BacterialForagingOptimization(60, 25, bound, [2, 2, 50, 4, 50, 0.25, 0.1, 0.2, 0.1, 10]) 234 | bfo.solve() -------------------------------------------------------------------------------- /萤火虫算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random 3 | import copy 4 | import matplotlib.pyplot as plt 5 | import math 6 | import ObjFunction 7 | 8 | 9 | class FAIndividual: 10 | 11 | ''' 12 | individual of firefly algorithm 13 | ''' 14 | 15 | def __init__(self, vardim, bound): 16 | ''' 17 | vardim: dimension of variables 18 | bound: boundaries of variables 19 | ''' 20 | self.vardim = vardim 21 | self.bound = bound 22 | self.fitness = 0. 23 | self.trials = 0 24 | 25 | def generate(self): 26 | ''' 27 | generate a random chromsome for firefly algorithm 28 | ''' 29 | len = self.vardim 30 | rnd = np.random.random(size=len) 31 | self.chrom = np.zeros(len) 32 | for i in range(0, len): 33 | self.chrom[i] = self.bound[0, i] + \ 34 | (self.bound[1, i] - self.bound[0, i]) * rnd[i] 35 | 36 | def calculateFitness(self): 37 | ''' 38 | calculate the fitness of the chromsome 39 | ''' 40 | self.fitness = ObjFunction.GrieFunc(self.vardim, self.chrom, self.bound) 41 | 42 | 43 | 44 | 45 | class FireflyAlgorithm: 46 | 47 | ''' 48 | The class for firefly algorithm 49 | ''' 50 | 51 | def __init__(self, sizepop, vardim, bound, MAXGEN, params): 52 | ''' 53 | sizepop: population sizepop 54 | vardim: dimension of variables 55 | bound: boundaries of variables 56 | MAXGEN: termination condition 57 | param: algorithm required parameters, it is a list which is consisting of [beta0, gamma, alpha] 58 | ''' 59 | self.sizepop = sizepop 60 | self.MAXGEN = MAXGEN 61 | self.vardim = vardim 62 | self.bound = bound 63 | self.population = [] 64 | self.fitness = np.zeros((self.sizepop, 1)) 65 | self.trace = np.zeros((self.MAXGEN, 2)) 66 | self.params = params 67 | 68 | def initialize(self): 69 | ''' 70 | initialize the population 71 | ''' 72 | for i in range(0, self.sizepop): 73 | ind = FAIndividual(self.vardim, self.bound) 74 | ind.generate() 75 | self.population.append(ind) 76 | 77 | def evaluate(self): 78 | ''' 79 | evaluation of the population fitnesses 80 | ''' 81 | for i in range(0, self.sizepop): 82 | self.population[i].calculateFitness() 83 | self.fitness[i] = self.population[i].fitness 84 | 85 | def solve(self): 86 | ''' 87 | evolution process of firefly algorithm 88 | ''' 89 | self.t = 0 90 | self.initialize() 91 | self.evaluate() 92 | best = np.max(self.fitness) 93 | bestIndex = np.argmax(self.fitness) 94 | self.best = copy.deepcopy(self.population[bestIndex]) 95 | self.avefitness = np.mean(self.fitness) 96 | self.trace[self.t, 0] = (1 - self.best.fitness) / self.best.fitness 97 | self.trace[self.t, 1] = (1 - self.avefitness) / self.avefitness 98 | print("Generation %d: optimal function value is: %f; average function value is %f" % ( 99 | self.t, self.trace[self.t, 0], self.trace[self.t, 1])) 100 | while (self.t < self.MAXGEN - 1): 101 | self.t += 1 102 | self.move() 103 | self.evaluate() 104 | best = np.max(self.fitness) 105 | bestIndex = np.argmax(self.fitness) 106 | if best > self.best.fitness: 107 | self.best = copy.deepcopy(self.population[bestIndex]) 108 | self.avefitness = np.mean(self.fitness) 109 | self.trace[self.t, 0] = (1 - self.best.fitness) / self.best.fitness 110 | self.trace[self.t, 1] = (1 - self.avefitness) / self.avefitness 111 | print("Generation %d: optimal function value is: %f; average function value is %f" % ( 112 | self.t, self.trace[self.t, 0], self.trace[self.t, 1])) 113 | 114 | print("Optimal function value is: %f; " % 115 | self.trace[self.t, 0]) 116 | print("Optimal solution is:") 117 | print(self.best.chrom) 118 | self.printResult() 119 | 120 | def move(self): 121 | ''' 122 | move the a firefly to another brighter firefly 123 | ''' 124 | for i in range(0, self.sizepop): 125 | for j in range(0, self.sizepop): 126 | if self.fitness[j] > self.fitness[i]: 127 | r = np.linalg.norm( 128 | self.population[i].chrom - self.population[j].chrom) 129 | beta = self.params[0] * \ 130 | np.exp(-1 * self.params[1] * (r ** 2)) 131 | # beta = 1 / (1 + self.params[1] * r) 132 | # print beta 133 | self.population[i].chrom += beta * (self.population[j].chrom - self.population[ 134 | i].chrom) + self.params[2] * np.random.uniform(low=-1, high=1, size=self.vardim) 135 | for k in range(0, self.vardim): 136 | if self.population[i].chrom[k] < self.bound[0, k]: 137 | self.population[i].chrom[k] = self.bound[0, k] 138 | if self.population[i].chrom[k] > self.bound[1, k]: 139 | self.population[i].chrom[k] = self.bound[1, k] 140 | self.population[i].calculateFitness() 141 | self.fitness[i] = self.population[i].fitness 142 | 143 | def printResult(self): 144 | ''' 145 | plot the result of the firefly algorithm 146 | ''' 147 | x = np.arange(0, self.MAXGEN) 148 | y1 = self.trace[:, 0] 149 | y2 = self.trace[:, 1] 150 | plt.plot(x, y1, 'r', label='optimal value') 151 | plt.plot(x, y2, 'g', label='average value') 152 | plt.xlabel("Iteration") 153 | plt.ylabel("function value") 154 | plt.title("Firefly Algorithm for function optimization") 155 | plt.legend() 156 | plt.show() 157 | 158 | if __name__ == "__main__": 159 | 160 | bound = np.tile([[-600], [600]], 25) 161 | fa = FireflyAlgorithm(60, 25, bound, 200, [1.0, 0.000001, 0.6]) 162 | fa.solve() -------------------------------------------------------------------------------- /蚁群算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | """ 5 | 蚁群算法流程: 6 | (1)初始化: 7 | 初始化参数:alpha:信息素启发因子([0-5]); beta:期望值启发因子([0-5);rou:信息素挥发因子([0.1-0.99]);种群大小population_size[10,100] 8 | 初始化蚂蚁种群:种群的大小为N,则初始化数组的大小就是(N,),如果是普通的函数优化的话,列数是自变量的个数 9 | 初始化信息素:第一代信息素采用第一代蚁群的适应度值表示 10 | (2)状态转移:根据上一代蚂蚁的信息素和距离等信息计算状态转移概率,根据状态转移概率进行局部搜索或者全局搜索 11 | (3)约束边界:也称为越界保护 12 | (4)选择:产生新种群的操作,根据目标函数值在原始蚁群和状态转移后的蚁群之间进行对比选择,如果原始蚁群的适应度更好,就保留,否则就转移 13 | (5)更新信息素:有具体的公式 14 | (6)对选择后的蚁群重复进行状态转移、约束边界和更新信息素3步,一直到结束。 15 | 16 | """ 17 | 18 | 19 | class ACO: 20 | def __init__(self, parameters): 21 | """ 22 | Ant Colony Optimization 23 | :param parameters: a list type,Like[iter,population_size,var_num_min,var_num_max] 24 | """ 25 | # 初始化 26 | # 初始化方法接受传入的参数,包括最大值,最小值,种群大小和迭代代数。 27 | # 通过这些参数初始化产生一个蚂蚁种群,并记录当前代全局最优位置。 28 | self.iter = parameters[0] # 迭代的次数 29 | self.population_size = parameters[1] # 种群的大小 30 | self.var_num = len(parameters[2]) # 自变量的个数 31 | self.bound = [] # 自变量的约束范围 32 | self.bound.append(parameters[2]) 33 | self.bound.append(parameters[3]) 34 | self.population_x = np.zeros((self.population_size, self.var_num)) # 所有蚂蚁的位置 35 | self.g_best = np.zeros((1, self.var_num)) # 全局蚂蚁最优的位置 36 | # 初始化第0代 初始的全局最优解 37 | temp = -1 38 | for i in range(self.population_size): # 对于每一只蚂蚁来说都会有一个潜在解 39 | for j in range(self.var_num): # 取出每一个变量,产生一个在[var_num_min,var_num_max]范围内的随机数 40 | self.population_x[i][j] = np.random.uniform(self.bound[0][j], self.bound[1][j]) 41 | fit = self.fitness(self.population_x[i]) 42 | if fit > temp: 43 | self.g_best = self.population_x[i] 44 | temp = fit 45 | print("初始种群:", self.population_x) 46 | 47 | def fitness(self, ind_var): 48 | """ 49 | 个体适应值计算 50 | """ 51 | x1 = ind_var[0] 52 | x2 = ind_var[1] 53 | x3 = ind_var[2] 54 | x4 = ind_var[3] 55 | y = x1 ** 2 + x2 ** 2 + x3 ** 3 + x4 ** 4 56 | return y 57 | 58 | # 更新位置信息和信息素信息 59 | def update_operator(self, gen, tau, tau_max): 60 | rou = 0.8 # 信息素挥发系数 61 | Q = 1 # 每只蚂蚁的信息素释放总量 62 | lamda = 1 / gen 63 | pi = np.zeros(self.population_size) 64 | for i in range(self.population_size): # 对于每一只蚂蚁 65 | for j in range(self.var_num): # 对于每一个变量 66 | pi[i] = (tau_max - tau[i]) / tau_max # 计算蚂蚁 i 的状态转移概率 67 | # 更新位置 68 | if pi[i] < np.random.uniform(0, 1): # 这里也可以直接使用一个常数来判断是进行局部搜索还是全局搜索 69 | # 局部搜索公式:new = old + r1 *step* lamda 70 | self.population_x[i][j] = self.population_x[i][j] + np.random.uniform(-1, 1) * lamda 71 | else: 72 | # 全局搜索公式:new = old + r2 *range 73 | self.population_x[i][j] = self.population_x[i][j] + np.random.uniform(-1, 1) * ( 74 | self.bound[1][j] - self.bound[0][j]) / 2 75 | # 越界保护 76 | if self.population_x[i][j] < self.bound[0][j]: 77 | self.population_x[i][j] = self.bound[0][j] 78 | if self.population_x[i][j] > self.bound[1][j]: 79 | self.population_x[i][j] = self.bound[1][j] 80 | 81 | 82 | # 更新每只蚂蚁的信息素 83 | tau[i] = (1 - rou) * tau[i] + Q * self.fitness(self.population_x[i]) # 蚁密模型 84 | 85 | # 更新全局最优值 86 | if self.fitness(self.population_x[i]) > self.fitness(self.g_best): 87 | self.g_best = self.population_x[i] 88 | 89 | tau_max = np.max(tau) 90 | 91 | return tau_max, tau # t_max是信息素最大的那个值,t存放着每一只蚂蚁在一代中的信息素 92 | 93 | # 主程序 94 | def main(self): 95 | popobj = [] 96 | best = np.zeros((1, self.var_num))[0] 97 | for gen in range(1, self.iter + 1): 98 | # 第一代的时候,初始的信息素根据第一代的适应度值计算 99 | if gen == 1: 100 | tau_init = np.array(list(map(self.fitness, self.population_x))) 101 | # map()是Python内置的高阶函数,它接受一个函数f 和一个list,并通过把函数f 依次作用在list的每一个元素上,得到一个新的list并返回,map函数一定是要经过list()转换的 102 | tau_max, tau = self.update_operator(gen, tau_init, np.max(tau_init)) 103 | else: 104 | # 状态转移:更新位置与信息素 105 | tau_max, tau = self.update_operator(gen, tau, tau_max) 106 | popobj.append(self.fitness(self.g_best)) 107 | print('############ Generation {} ############'.format(str(gen))) 108 | print(self.g_best) 109 | print(self.fitness(self.g_best)) 110 | if self.fitness(self.g_best) > self.fitness(best): 111 | best = self.g_best.copy() 112 | print('最好的位置:{}'.format(best)) 113 | print('最大的函数值:{}'.format(self.fitness(best))) 114 | print("---- End of (successful) Searching ----") 115 | 116 | plt.figure() 117 | plt.title("Figure1") 118 | plt.xlabel("iterators", size=14) 119 | plt.ylabel("fitness", size=14) 120 | t = [t for t in range(1, self.iter + 1)] 121 | plt.plot(t, popobj, color='b', linewidth=2) 122 | plt.show() 123 | 124 | 125 | if __name__ == '__main__': 126 | iter = 100 127 | population_size = 100 128 | low = [1, 1, 1, 1] 129 | up = [30, 30, 30, 30] 130 | parameters = [iter, population_size, low, up] 131 | aco = ACO(parameters) 132 | aco.main() 133 | -------------------------------------------------------------------------------- /遗传算法.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from matplotlib import cm 4 | from mpl_toolkits.mplot3d import Axes3D 5 | 6 | DNA_SIZE = 24 7 | POP_SIZE = 200 8 | CROSSOVER_RATE = 0.8 9 | MUTATION_RATE = 0.005 10 | N_GENERATIONS = 50 11 | X_BOUND = [-3, 3] 12 | Y_BOUND = [-3, 3] 13 | 14 | 15 | def F(x, y):#目标函数 16 | return 3 * (1 - x) ** 2 * np.exp(-(x ** 2) - (y + 1) ** 2) - 10 * (x / 5 - x ** 3 - y ** 5) * np.exp( 17 | -x ** 2 - y ** 2) - 1 / 3 ** np.exp(-(x + 1) ** 2 - y ** 2) 18 | 19 | 20 | def plot_3d(ax):#绘图 21 | X = np.linspace(*X_BOUND, 100) 22 | Y = np.linspace(*Y_BOUND, 100) 23 | X, Y = np.meshgrid(X, Y) 24 | Z = F(X, Y) 25 | ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm) 26 | ax.set_zlim(-10, 10) 27 | ax.set_xlabel('x') 28 | ax.set_ylabel('y') 29 | ax.set_zlabel('z') 30 | plt.pause(3) 31 | plt.show() 32 | 33 | 34 | def get_fitness(pop):#计算适应度(也就是目标函数的相对值) 35 | x, y = translateDNA(pop) 36 | pred = F(x, y) 37 | return (pred - np.min( 38 | pred)) + 1e-3 # 减去最小的适应度是为了防止适应度出现负数,通过这一步fitness的范围为[0, np.max(pred)-np.min(pred)],最后在加上一个很小的数防止出现为0的适应度 39 | 40 | 41 | def translateDNA(pop): # pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目 42 | x_pop = pop[:, 1::2] # 奇数列表示X 43 | y_pop = pop[:, ::2] # 偶数列表示y 44 | 45 | # pop:(POP_SIZE,DNA_SIZE)*(DNA_SIZE,1) --> (POP_SIZE,1) 46 | x = x_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (X_BOUND[1] - X_BOUND[0]) + X_BOUND[0] 47 | y = y_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (Y_BOUND[1] - Y_BOUND[0]) + Y_BOUND[0] 48 | return x, y 49 | 50 | 51 | def crossover_and_mutation(pop, CROSSOVER_RATE=0.8): 52 | new_pop = [] 53 | for father in pop: # 遍历种群中的每一个个体,将该个体作为父亲 54 | child = father # 孩子先得到父亲的全部基因(这里我把一串二进制串的那些0,1称为基因) 55 | if np.random.rand() < CROSSOVER_RATE: # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉 56 | mother = pop[np.random.randint(POP_SIZE)] # 再种群中选择另一个个体,并将该个体作为母亲 57 | cross_points = np.random.randint(low=0, high=DNA_SIZE * 2) # 随机产生交叉的点 58 | child[cross_points:] = mother[cross_points:] # 孩子得到位于交叉点后的母亲的基因 59 | mutation(child) # 每个后代有一定的机率发生变异 60 | new_pop.append(child) 61 | 62 | return new_pop 63 | 64 | 65 | def mutation(child, MUTATION_RATE=0.003): 66 | if np.random.rand() < MUTATION_RATE: # 以MUTATION_RATE的概率进行变异 67 | mutate_point = np.random.randint(0, DNA_SIZE) # 随机产生一个实数,代表要变异基因的位置 68 | child[mutate_point] = child[mutate_point] ^ 1 # 将变异点的二进制为反转 69 | 70 | 71 | def select(pop, fitness): # nature selection wrt pop's fitness 72 | idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True, 73 | p=(fitness) / (fitness.sum())) 74 | return pop[idx] 75 | 76 | 77 | def print_info(pop): 78 | fitness = get_fitness(pop) 79 | max_fitness_index = np.argmax(fitness) 80 | print("max_fitness:", fitness[max_fitness_index]) 81 | x, y = translateDNA(pop) 82 | print("最优的基因型:", pop[max_fitness_index]) 83 | print("(x, y):", (x[max_fitness_index], y[max_fitness_index])) 84 | 85 | 86 | if __name__ == "__main__": 87 | fig = plt.figure() 88 | ax = Axes3D(fig) 89 | plt.ion() # 将画图模式改为交互模式,程序遇到plt.show不会暂停,而是继续执行 90 | plot_3d(ax) 91 | 92 | pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE * 2)) # matrix (POP_SIZE, DNA_SIZE) 93 | for _ in range(N_GENERATIONS): # 迭代N代 94 | x, y = translateDNA(pop) 95 | if 'sca' in locals(): 96 | sca.remove() 97 | sca = ax.scatter(x, y, F(x, y), c='black', marker='o'); 98 | plt.show(); 99 | plt.pause(0.1) 100 | pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE)) 101 | # F_values = F(translateDNA(pop)[0], translateDNA(pop)[1])#x, y --> Z matrix 102 | fitness = get_fitness(pop) 103 | pop = select(pop, fitness) # 选择生成新的种群 104 | 105 | print_info(pop) 106 | plt.ioff() 107 | plot_3d(ax) 108 | -------------------------------------------------------------------------------- /遗传算法_new.py: -------------------------------------------------------------------------------- 1 | # Step1:按照一定的初始化方法产生初始种群P(t),t=0 2 | # Step2:评价种群P(t),计算每个个体的适应度值 3 | # Step3:判断是否满足终止条件,如果满足则输出结果;否则转到步骤4 4 | # Step4:按照选择/交叉/变异等遗传算子产生C(t) 5 | # Step5:P(t) = C(t), 转到步骤2,t=t+1 6 | 7 | # 确定问题:求解2*sin(x)+cos(x)的最大值 8 | 9 | # Step1:按照一定的初始化方法产生初始种群:其中需要的参数为种群的大小以及 二进制基因型的位数 10 | # 比如x的取值范围时[0,7],那么这个时候x就可以用三位二进制表示 11 | import random 12 | import math 13 | import matplotlib.pyplot as plt 14 | 15 | 16 | def species_origin(population_size, chromosome_length): 17 | population = [[]] # 二维列表,包含染色体和基因 18 | for i in range(population_size): 19 | temporary = [] # 染色体暂存器 20 | for j in range(chromosome_length): 21 | temporary.append(random.randint(0, 1)) # 随机产生一个染色体,由二进制数组成 22 | population.append(temporary) # 将染色体添加到种群中 23 | return population[1:] # 将种群返回,种群时一个二维数组,个体和染色体两维 24 | 25 | 26 | # 编码:将二进制的染色体基因型编码为十进制的表现型 27 | # 所需要的参数:种群以及染色体的长度 28 | def translation(population, chromosome_length): 29 | temporary = [] 30 | for i in range(len(population)): # 遍历所有的种群,对于种群中的每一个个体,进行编码 31 | total = 0 32 | for j in range(chromosome_length): 33 | # 编码的方式就是从第一个基因开始,对2求幂再求和,就是二进制转十进制的思想 34 | total = total + population[i][j] * (math.pow(2, j)) 35 | # 一个染色体编码完成,由一个二进制数编码为了一个十进制数 36 | temporary.append(total) 37 | # 返回种群中所有个体编码完成后的十进制数 38 | return temporary 39 | 40 | 41 | # Step2:评价种群P(t),计算每一个个体的适应度值 42 | # 在本例中,函数值总取非负值,以函数最大值为优化目标,所以可以直接将目标函数作为适应度函数。 43 | def function(population, chtomosome_length, max_value): 44 | temporary = [] 45 | function1 = [] 46 | temporary = translation(population, chtomosome_length) # 暂存种群中的所有的染色体 47 | for i in range(len(temporary)): 48 | # 遍历种群中的每一个个体,temporary[i]表示其中一个个体的十进制数 49 | # 一个基因代表一个决策变量,其算法是先转化为十进制,然后除以2的基因个数次方-1 (固定公式) 50 | # 解码 51 | x = temporary[i] * max_value / (math.pow(2, chtomosome_length) - 1) 52 | function1.append(2 * math.sin(x) + math.cos(x)) 53 | return function1 54 | 55 | 56 | # Step3:判断是否满足终止条件,如果不满足进行Step4 57 | 58 | 59 | # Step4:按照选择/交叉/变异等遗传算子产生子代 60 | # 选择操作 61 | def fitness(function1): 62 | fitness1 = [] 63 | min_fitness = mf = 0 64 | for i in range(len(function1)): 65 | # 在这里就用到了 目标函数值到个体适应度之间的转换关系了,要保证适应度值为非负,这样才能保证被选择的概率非负, 66 | # 引入mf,是一个相对比较小的数,可以是预先取定的,也可以是进化到当前代为止的最小目标函数值 67 | if (function1[i] + mf > 0): 68 | temporary = mf + function1[i] 69 | else: # 如果适应度小于0,就定为0 70 | temporary = 0.0 71 | fitness1.append(temporary) # 将适应度添加到列表中 72 | # 返回种群中每个个体的适应度函数值 73 | return fitness1 74 | 75 | 76 | # 计算适应度总和 77 | def sum(fitness1): 78 | total = 0 79 | for i in range(len(fitness1)): 80 | total += fitness1[i] 81 | return total 82 | 83 | 84 | # 计算适应度斐波那契列表,这里是为了求出累积的适应度 85 | # 其实这一步就是计算累积概率,为什么呢?上一步计算得到每一个个体被选择的概率时,可以容易看出,总和为1, 86 | # 现在需要将这N个个体按照比例放入0-1范围的线段里,每一个个体应该用多长的线段呢?用线段的长度代表被选择概率 87 | # 因为轮盘赌没有方向,所以再代码中,我们生成一个[0.1]中的随机数,落在0-1的线段上的哪一段位置上的概率就是各个个体被选择的概率。 88 | # https://blog.csdn.net/weixin_39068956/article/details/105121469 89 | def cumsum(fitness1): 90 | for i in range(len(fitness1) - 2, -1, -1): 91 | # range(start,stop,[step]) 从len(fitness1)-2 到 0,步长为-1 92 | # 倒计数 93 | total = 0 94 | j = 0 95 | while (j <= i): 96 | total += fitness1[j] 97 | j += 1 98 | fitness1[i] = total 99 | fitness1[len(fitness1) - 1] = 1 100 | 101 | 102 | # 选择种群中个体适应度最大的个体.所需要的参数是种群以及适应度值 103 | def selection(population, fitness1): 104 | new_fitness = [] # 单个公式暂存器 105 | # 将所有的适应度求和 106 | total_fitness = sum(fitness1) 107 | # 对于每一个个体,将其适应度概率化 108 | for i in range(len(fitness1)): 109 | new_fitness.append(fitness1[i] / total_fitness) 110 | 111 | # new_fitness里面现在存放的是累积概率 112 | cumsum(new_fitness) 113 | 114 | ms = [] # 存活的种群 115 | # 求出种群的长度 116 | population_length = pop_len = len(population) 117 | # 根据随机数确定哪几个能够存活 118 | for i in range(pop_len): 119 | # 产生种群个数的随机值,比如种群数为4,那么就产生4个随机数 120 | ms.append(random.random()) # random() 方法返回随机生成的一个实数,它在[0,1)范围内。 121 | # 存活的种群排序 122 | ms.sort() 123 | 124 | fitin = 0 # 125 | newin = 0 # 用来遍历轮盘赌产生的随机数 126 | new_population = new_pop = population 127 | 128 | # 轮盘赌方式 129 | while newin < pop_len: # 循环次数为种群的大小 130 | if (ms[newin] < new_fitness[fitin]): 131 | # 如果产生的随机数小于累积概率,即为被选中的个体,直接将此时的个体赋值给new_pop即可,然后进行下一次轮盘赌选择 132 | new_pop[newin] = population[fitin] 133 | newin += 1 134 | else: # 如果产生的随机数大于累积概率,就比较下一个累积概率,一直到选出一个个体为止 135 | fitin += 1 136 | population = new_pop 137 | 138 | 139 | # 交叉操作,所需要的参数:种群以及交叉概率 140 | def crossover(population, pcB00): 141 | pop_len = len(population) 142 | 143 | for i in range(pop_len - 1): 144 | # 随机生成单点交叉点 145 | cpoint = random.randint(0, len(population[0])) 146 | temporary1 = [] 147 | temporary2 = [] 148 | 149 | # 将temporary1作为暂存器,暂时存放第i个染色体中的前0到cpoint个基因 150 | temporary1.extend(population[i][0:cpoint]) 151 | # 然后再把第i+1个染色体中的后cpoint到第i个染色体中的基因个数补充到temporary1后面 152 | temporary1.extend(population[i + 1][cpoint:len(population[i])]) 153 | 154 | # 将temporary2作为暂存器,在那时存放第i+1个染色体中的前0到cpoint个基因 155 | temporary2.extend(population[i + 1][0:cpoint]) 156 | # 然后再将第i个染色体中的后cpoint到第i个染色体中的基因个数补充到tempporary2后面 157 | temporary2.extend(population[i][cpoint:len(population[i])]) 158 | 159 | # 第i个染色体和第i+1个染色体基因重组。交叉完成 160 | population[i] = temporary1 161 | population[i + 1] = temporary2 162 | 163 | 164 | # 变异算子操作 165 | def mutation(population, pm): 166 | # 种群中个体的数量 167 | px = len(population) 168 | # 个体中基因/染色体的位数 169 | py = len(population[0]) 170 | 171 | for i in range(px): 172 | if (random.random() < pm): # 如果小于pm就发生变异 173 | # 生成0-py-1之间的随机数,就随机产生变异点 174 | mpoint = random.randint(0, py - 1) 175 | # 将mpoint个基因进行单点随机变异,变为0或者1 176 | if (population[i][mpoint] == 1): 177 | population[i][mpoint] = 0 178 | else: 179 | population[i][mpoint] = 1 180 | 181 | 182 | # 将每一个染色体都转化成十进制 max_value为基因最大值,为了后面画图用 183 | def b2d(b, max_value, chromosome_length): 184 | total = 0 185 | for i in range(len(b)): 186 | total = total + b[i] * math.pow(2, i) 187 | # 从第一位开始,每一位对2求幂,然后求和,得到十进制数? 188 | total = total * max_value / (math.pow(2, chromosome_length) - 1) 189 | return total 190 | 191 | 192 | # 寻找最好的适应度和个体 193 | def best(population, fitness1): 194 | px = len(population) 195 | bestindividual = [] 196 | bestfitness = fitness1[0] 197 | 198 | for i in range(1, px): 199 | # 循环找出最大的适应度,适应度最大的也就是最好的个体 200 | if (fitness1[i] > bestfitness): 201 | bestfitness = fitness1[i] 202 | bestindividual = population[i] 203 | 204 | return [bestindividual, bestfitness] 205 | 206 | 207 | # 主程序 208 | population_size = 500 209 | max_value = 10 210 | chromosome_length = 10 211 | pc = 0.6 212 | pm = 0.01 213 | results = [[]] 214 | fitness1 = [] 215 | fitmean = [] 216 | 217 | # 产生一个初始的种群 218 | population = pop = species_origin(population_size, chromosome_length) 219 | 220 | # 迭代500次 221 | for i in range(population_size): 222 | function1 = function(population, chromosome_length, max_value) 223 | fitness1 = fitness(function1) 224 | best_individual, best_fitness = best(population, fitness1) 225 | results.append([best_fitness, b2d(best_individual, max_value, chromosome_length)]) 226 | 227 | selection(population, fitness1) 228 | crossover(population, pc) 229 | mutation(population, pm) 230 | 231 | results = results[1:] 232 | results.sort() 233 | X = [] 234 | Y = [] 235 | for i in range(500): 236 | X.append(i) 237 | Y.append(results[i][0]) 238 | print("结束") 239 | plt.plot(X, Y) 240 | plt.show() 241 | --------------------------------------------------------------------------------