opt_alg.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import numpy as np
  2. import pandas as pd
  3. import geatpy as ea
  4. from ._utils.config_info import ConfigInfo
  5. from .opt_obj import Opt
  6. All_Algorithm = {
  7. 'soea_DE_rand_1_L_templet':{
  8. 'templet': ea.soea_DE_rand_1_L_templet,
  9. 'param' : {'F':0.6,'Cr':0.85,'L':15}
  10. },
  11. 'soea_DE_currentToBest_1_L_templet':{
  12. 'templet': ea.soea_DE_currentToBest_1_L_templet,
  13. 'param' : {'F':0.6,'Cr':0.85,'L':15}
  14. },
  15. 'soea_DE_best_1_L_templet':{
  16. 'templet': ea.soea_DE_best_1_L_templet,
  17. 'param' : {'F':0.5,'Cr':0.8,'L':15}
  18. },
  19. }
  20. def main(opt_obj:Opt,allow_neg_opt:bool,config=None) -> list:
  21. config_info = ConfigInfo(config)
  22. # 组件配置参数检查
  23. config_info.check_property_exist({'NIND':'种群数量','MAXGEN':'迭代次数'})
  24. # 种群参数
  25. Encoding = 'RI'
  26. NIND = config['NIND']
  27. Field = ea.crtfld(
  28. Encoding = Encoding,
  29. varTypes = opt_obj.varTypes,
  30. ranges = opt_obj.ranges,
  31. borders = opt_obj.borders,
  32. precisions = opt_obj.var_precis
  33. )
  34. population = ea.Population(Encoding,Field,NIND)
  35. # 算法参数
  36. templete = All_Algorithm[config['algorithm']]['templet']
  37. param = All_Algorithm[config['algorithm']]['param']
  38. Algorithm = templete(opt_obj,population)
  39. Algorithm.MAXGEN = config['MAXGEN'] # 复杂问题需增加代数。
  40. Algorithm.F = param['F'] # 0.5~0.8 增大 F 增强全局搜索,但可能降低收敛速度。
  41. Algorithm.Cr = param['Cr'] # 0.8~1.0 高 Cr 适合强相关变量,低 Cr 增强多样性。
  42. Algorithm.L = param['L'] # 5~20 变量相关性越强,L 应越大。高维问题可设为变量维度的 10%~20%。
  43. Algorithm.logTras = int(config['MAXGEN']/10)
  44. Algorithm.verbose = False
  45. Algorithm.drawing = 0
  46. [bestindi,pop] = Algorithm.run()
  47. # 检查是否有可行解
  48. #TODO 设定没有可行解时取当前解
  49. if len(bestindi) == 0:
  50. print_cv(pop.CV,opt_obj.constrains,opt_obj.cur_sys_constrains_cfl)
  51. raise Exception('没有可行解')
  52. opt_system_x = get_opt_system_x(opt_obj,bestindi) # 完整的系统模型输入
  53. opt_var = opt_system_x.loc[:,opt_obj.name_opt_vars] # 优化变量
  54. sys_before_after_output = get_sys_output_before_after(opt_obj,opt_system_x) # 优化前后系统模型输出
  55. opt_var_before_after = get_opt_var_before_after(opt_obj,opt_var) # 优化前后系统模型输入(优化变量)
  56. # 打印优化后的结果对比
  57. alg_log = print_opt_result(Algorithm,bestindi,opt_obj,sys_before_after_output,opt_var_before_after)
  58. # 检查本次优化是否为负优化
  59. check_neg_opt(opt_obj,sys_before_after_output,allow_neg_opt)
  60. # 组件输出并校验
  61. process_list = [alg_log,opt_var_before_after,sys_before_after_output]
  62. result_list = process_list + config_info.split_df(method='id',df=opt_var,by_group='优化变量')
  63. return result_list
  64. def print_opt_result(
  65. Algorithm,
  66. bestindi,
  67. opt_obj : Opt,
  68. sys_before_after_output: pd.DataFrame,
  69. opt_var_before_after : pd.DataFrame
  70. ) -> pd.DataFrame:
  71. print('+'*20+' 优化结果 '+'+'*20)
  72. print('\n算法迭代过程:')
  73. with pd.option_context('display.max_rows', None):
  74. with pd.option_context('display.max_columns', None):
  75. alg_log = pd.DataFrame(Algorithm.log).round(2)
  76. print(alg_log)
  77. print(f'\n评价次数 : {Algorithm.evalsNum}')
  78. print(f'所用时间 : {round(Algorithm.passTime,2)}秒')
  79. print(f'最优的目标函数值({opt_obj.opt_target}) : {round(bestindi.ObjV[0][0],4)}')
  80. # print('\n最后一次迭代的系统模型输出:')
  81. # print(opt_obj.data_y.round(4).drop_duplicates().T)
  82. print('\n优化前后控制变量的对比:')
  83. print(opt_var_before_after)
  84. print('\n优化前后系统模型输出的结果对比:')
  85. # 优化后系统模型的结果不唯一,取离优化目标最接近的结果
  86. print(sys_before_after_output)
  87. print('\n系统模型的初始输入违背约束条件的情况:')
  88. print_sys_init_constrains(opt_obj.cur_sys_constrains_cfl)
  89. print(' \n系统模型调用时长统计:')
  90. opt_obj.system_model.summary_past_time()
  91. print('\n'+'+'*50)
  92. return alg_log
  93. def print_cv(
  94. cv : np.ndarray,
  95. constrains : list,
  96. cur_sys_constrains_cfl: dict
  97. ) -> None:
  98. #TODO 增加每一次迭代的CV结果
  99. # 最后一次迭代的CV
  100. print('每一个约束条件最后一次迭代的CV(大于0表明不满足约束条件):')
  101. last_cv = [
  102. cv.mean(axis=0),
  103. cv.max(axis=0),
  104. cv.min(axis=0),
  105. (cv<0).sum(axis=0),
  106. (cv<0).mean(axis=0),
  107. ]
  108. last_cv = pd.DataFrame(
  109. data=np.vstack(last_cv).T,
  110. columns=['Mean_CV','Max_CV','Min_CV','Count_CV<0','Pct_CV<0']
  111. )
  112. print(last_cv)
  113. #TODO 联合各个约束条件检查CV
  114. print('\n对应以下约束条件:')
  115. for idx,cst in enumerate(constrains):
  116. print(f'{idx} : {cst}<0')
  117. print('\n系统模型的初始输入违背约束条件的情况:')
  118. print_sys_init_constrains(cur_sys_constrains_cfl)
  119. def get_opt_system_x(opt_obj:Opt,bestindi) -> pd.DataFrame:
  120. # 优化变量的优化结果
  121. data = opt_obj.insert_sync_var(bestindi.Phen.reshape(1,-1))
  122. opt_var = pd.DataFrame(
  123. data = data,
  124. columns = opt_obj.name_opt_vars,
  125. index = opt_obj.index
  126. )
  127. system_x = pd.concat([opt_var,opt_obj.sys_var,opt_obj.oth_var],axis=1)
  128. # 将优化结果中映射边界的对应的变量进行还原
  129. system_x = opt_obj.restore_data(system_x)
  130. return system_x
  131. def get_sys_output_before_after(opt_obj:Opt,system_x):
  132. # 优化前后,系统模型输出的变化
  133. opt_system_y = opt_obj.system_model.predict(system_x)
  134. sys_before_after_output = (
  135. pd.concat([
  136. opt_obj.current_system_y,
  137. opt_system_y
  138. ],axis=0)
  139. .transpose()
  140. .set_axis(['Before','After'],axis=1)
  141. .assign(
  142. Diff = lambda dt:dt.After - dt.Before,
  143. Diff_pct = lambda dt:((dt.After - dt.Before)/dt.Before * 100).round(2).astype('str') + '%'
  144. )
  145. .round(2)
  146. )
  147. return sys_before_after_output
  148. def get_opt_var_before_after(opt_obj,opt_var):
  149. # 优化前后,优化变量的变化
  150. result_opt = (
  151. pd.concat([opt_obj.opt_var,opt_var],axis=0)
  152. .reset_index(drop=True)
  153. .transpose()
  154. .set_axis(['Before','After'],axis=1)
  155. .assign(
  156. Diff = lambda dt:dt.After - dt.Before,
  157. Diff_pct = lambda dt:((dt.After - dt.Before)/dt.Before * 100).round(2).astype('str') + '%'
  158. )
  159. .round(2)
  160. )
  161. return result_opt
  162. def check_neg_opt(opt_obj,sys_before_after_output,allow_neg_opt):
  163. if allow_neg_opt is None:
  164. allow_neg_opt = False
  165. if allow_neg_opt is True:
  166. return None
  167. if not isinstance(allow_neg_opt,bool):
  168. raise Exception(f'判断是否需要校验负优化的输入不是布尔值({type(allow_neg_opt)})')
  169. # 检查本次优化是否为负优化
  170. raw_pred = sys_before_after_output.at[opt_obj.opt_target,'Before']
  171. opt_pred = sys_before_after_output.at[opt_obj.opt_target,'After']
  172. neg_min_opt = (opt_obj.maxormins[0] == 1) and (opt_pred > raw_pred)
  173. neg_max_opt = (opt_obj.maxormins[0] == -1) and (opt_pred < raw_pred)
  174. if neg_min_opt or neg_max_opt:
  175. raise Exception(f'出现负优化,当前值为{raw_pred},优化后为{opt_pred}')
  176. return None
  177. def print_sys_init_constrains(cur_sys_constrains_cfl:dict):
  178. # 系统模型的初始输入违背约束条件的情况
  179. for cst_type,var_message in cur_sys_constrains_cfl.items():
  180. # 约束类型(边界/可行性)
  181. print(cst_type.upper())
  182. if isinstance(var_message,dict):
  183. for var_name,message in var_message.items():
  184. print(var_name+' : '+message)
  185. if isinstance(var_message,list):
  186. for message in var_message:
  187. print(message)