main.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. from typing import Union
  2. import numpy as np
  3. import pandas as pd
  4. from .opt_obj import Opt
  5. from .opt_alg import main as opt_alg_main
  6. from .constrains.build import main as build_all_constrains
  7. from ._utils.config_info import ConfigInfo
  8. from .model.diagnosis import ModelDiag
  9. def main(*args, system_model=None, config=None):
  10. config_info = ConfigInfo(config=config)
  11. group_data = config_info.get_io_group_info(io='in',type='data',data=args)
  12. group_point = config_info.get_io_group_info(io='in',type='point_id')
  13. check_var_data(group_data) # 校验数据的维度
  14. # 组件输入一:模型变量
  15. group_opt_var = group_data.get('优化变量')
  16. group_sys_var = group_data.get('系统变量')
  17. group_oth_var = group_data.get('其他变量')
  18. group_opt_col = group_point.get('优化变量')
  19. group_sys_col = group_point.get('系统变量')
  20. group_oth_col = group_point.get('其他变量')
  21. # 组件输入二:外部变量
  22. group_cst_var = group_data.get('外部变量')
  23. group_cst_col = group_point.get('外部变量')
  24. # 组件输入三:动态配置项
  25. group_dyn_cfg = group_data.get('动态配置',[None])
  26. allow_neg_opt = group_dyn_cfg[0] # 是否需要校验负优化
  27. # 初始化边界条件
  28. boundary,boundary_insert = get_boundary(group_opt_var)
  29. lb,ub,var_type,var_precis,collection_map,var_map = init_boundary(boundary)
  30. opt_var = get_opt_var(group_opt_var,group_opt_col)
  31. sys_var = get_sys_var(group_sys_var,group_sys_col)
  32. oth_var = get_oth_var(group_oth_var,group_oth_col,index=opt_var.index)
  33. cst_var = get_cst_var(group_cst_var,group_cst_col,index=opt_var.index)
  34. # 初始化可行性约束,动态可行性约束需要提前解析
  35. constrains = build_all_constrains(config)
  36. # 系统模型
  37. if system_model is None:
  38. from .model.model import main as get_system_model
  39. system_model = get_system_model(config)
  40. # 优化对象
  41. opt_object = Opt(
  42. lb = lb,
  43. ub = ub,
  44. varTypes = var_type,
  45. var_precis = var_precis,
  46. maxormins = 1 if config['dir_min'] is True else -1,
  47. collection_map = collection_map,
  48. var_map = var_map,
  49. boundary_insert = boundary_insert,
  50. opt_var = opt_var,
  51. sys_var = sys_var,
  52. system_model = system_model,
  53. oth_var = oth_var,
  54. cst_var = cst_var,
  55. opt_target = config['target'],
  56. constrains = constrains
  57. )
  58. # 系统模型诊断
  59. diag = config.get('diag_model',True)
  60. if diag == True:
  61. model_diag = ModelDiag(
  62. model = system_model,
  63. data = opt_object.current_system_x,
  64. c_var = opt_object.name_opt_vars_c,
  65. d_var = 1,
  66. )
  67. model_diag.summary_diag()
  68. # 优化算法
  69. # 是否允许负优化,组件的配置或输入中任意一处允许负优化,则不检查负优化
  70. allow_neg_opt_config = config_info.get_property('allow_neg_opt',default=False)
  71. allow_neg_opt = any([allow_neg_opt,allow_neg_opt_config])
  72. result_list = opt_alg_main(opt_obj = opt_object, allow_neg_opt = allow_neg_opt, config =config)
  73. # 输出中增加系统模型的初始输出(对应系统模型的初始输入)
  74. output_groups = config_info.get_io_group_info(io='out',type='point_id')
  75. result_list = result_append_init_sys_y(result_list,output_groups,opt_object)
  76. return result_list
  77. def check_var_data(group_data) -> None:
  78. for name,data in group_data.items():
  79. if not isinstance(data,pd.DataFrame):
  80. continue
  81. if data.shape[0] == 1:
  82. raise Exception(f'{name}的数据行数不等于1,不满足要求,数据为{data}')
  83. def get_opt_var(group_opt_var:list,group_opt_col:list) -> pd.DataFrame:
  84. opt_var = []
  85. for bound_info in group_opt_var:
  86. opt_var.append(bound_info['cur_val'])
  87. opt_var = pd.concat(opt_var,axis=1)
  88. opt_var.columns = group_opt_col
  89. return opt_var
  90. def get_sys_var(group_sys_var:list,group_sys_col:list) -> Union[pd.DataFrame,None]:
  91. if group_sys_var is None or len(group_sys_var)==0:
  92. print('【警告】未获取到"系统变量",确保实际不存在该变量 ')
  93. sys_var = None
  94. else:
  95. group_sys_var = [df.iloc[:,[0]] for df in group_sys_var]
  96. sys_var = pd.concat(group_sys_var,axis=1)
  97. sys_var.columns = group_sys_col
  98. return sys_var
  99. def get_oth_var(group_oth_var:list,group_oth_col:list,index) -> Union[pd.DataFrame,None]:
  100. oth_var_exist = group_oth_col is not None and len(group_oth_var) > 0
  101. if oth_var_exist:
  102. is_oth_var_df = all([isinstance(df,pd.DataFrame) for df in group_oth_var])
  103. if not oth_var_exist:
  104. # print('【警告】未获取到"其他变量",确保实际不存在该变量 ')
  105. oth_var = None
  106. elif is_oth_var_df and oth_var_exist:
  107. group_oth_var = [df.iloc[:,[0]] for df in group_oth_var]
  108. oth_var = pd.concat(group_oth_var,axis=1)
  109. oth_var.columns = group_oth_col
  110. elif (not is_oth_var_df) and oth_var_exist:
  111. print('【警告】未获取到有效的"其他变量",用0值代替所有该类变量 ')
  112. oth_var = pd.DataFrame(
  113. data = np.zeros_like(group_oth_col,dtype='float').reshape(1,-1),
  114. columns = group_oth_col,
  115. index = index
  116. )
  117. return oth_var
  118. def get_cst_var(group_cst_var:list,group_cst_col:list,index) -> Union[pd.DataFrame,None]:
  119. group_cst_var = None if (group_cst_var is None) or (len(group_cst_var)==0) else group_cst_var
  120. group_cst_col = None if (group_cst_col is None) or (len(group_cst_col)==0) else group_cst_col
  121. if group_cst_var is None or len(group_cst_var) == 0:
  122. # print('【警告】未获取到"外部变量",确保实际不存在该变量 ')
  123. return None
  124. new_group_cst_var = []
  125. # 校验数据类型,并重置Index(对齐)和Columns(便于引用)
  126. for var in group_cst_var:
  127. if not isinstance(var,pd.DataFrame):
  128. raise Exception(f'外部变量中存在错误的数据类型{type(var)}({var})')
  129. if var.shape[0] != 1:
  130. raise Exception(f'外部变量的数据形状有误{var.shape}(var)')
  131. var.index = index
  132. new_group_cst_var.append(var.iloc[:,[0]])
  133. cst_var = pd.concat(new_group_cst_var,axis=1)
  134. cst_var.columns = group_cst_col
  135. return cst_var
  136. def get_boundary(group_opt_var:list) -> dict:
  137. boundary = {} # {'id1':boundary_info1 , 'id2':boundary_info2}
  138. boundary_insert = {} # {0:0, 1:2, 3:1} 0位置插入0条,1位置插入2条,3位置插入1条
  139. print('-'*20+'边界条件'+'-'*20)
  140. pos_group_id = -1
  141. for idx,bound_info in enumerate(group_opt_var):
  142. print('-'*20+ str(idx) +'-'*20)
  143. for k,v in bound_info.items():
  144. v = v.iat[0,0] if isinstance(v,pd.DataFrame) else v
  145. print(f'{k} : {v} \n')
  146. if bound_info['id'] not in boundary.keys():
  147. pos_group_id += 1
  148. # 多个优化变量属于一个组内时(相同id),所有边界的信息以该组的id变量为准
  149. boundary[bound_info['id']] = bound_info # boundary 仅保留唯一的id
  150. boundary_insert[pos_group_id] = 0 # 插入的位置:插入的数量
  151. else:
  152. boundary_insert[pos_group_id] += 1
  153. return boundary,boundary_insert
  154. def init_boundary(all_boundary) -> tuple:
  155. # 生成边界
  156. lb = [] # 所有类型边界
  157. ub = [] # 所有类型边界
  158. var_type = [] # 所有类型边界
  159. var_precis = [] # 区间类边界
  160. collection_map = {} # 集合类边界/映射类边界 {'u1_name':{0:u1_a, 1:u1_b}}
  161. var_map = {} # 映射类边界 {'u1_name':{0:x1_a, 1:x1_b}}
  162. for boundary_id,boundary_info in all_boundary.items():
  163. boundary_type = boundary_info.get('boundary_type')
  164. var_name = boundary_info.get('var_name')
  165. # 区间类型的边界
  166. if boundary_type == 'interval':
  167. lb.append(boundary_info.get('lb'))
  168. ub.append(boundary_info.get('ub'))
  169. var_type.append(boundary_info.get('var_type'))
  170. var_precis.append(boundary_info.get('var_precis'))
  171. # 集合类型的边界
  172. elif boundary_type == 'collection':
  173. # 序号对应的数值也应该从小到大排序
  174. collection = boundary_info.get('collection')
  175. lb.append(0)
  176. ub.append(len(collection)-1)
  177. var_type.append(1)
  178. var_precis.append(0)
  179. collection_map[var_name] = dict(enumerate(collection))
  180. # 映射类型边界
  181. elif boundary_type == 'map':
  182. collection = boundary_info.get('collection')
  183. lb.append(0)
  184. ub.append(len(collection)-1)
  185. var_type.append(1)
  186. var_precis.append(0)
  187. collection_map[var_name] = dict(enumerate(collection))
  188. var_map[var_name] = boundary_info.get('var_map')
  189. else:
  190. raise ValueError('边界类型有误')
  191. return lb,ub,var_type,var_precis,collection_map,var_map
  192. def result_append_init_sys_y(result:list,output_groups:dict,opt_obj:Opt):
  193. if '初始输出' not in output_groups.keys():
  194. return result
  195. if len(output_groups['初始输出']) == 0:
  196. return result
  197. init_sys_y = []
  198. for y_col in output_groups['初始输出']:
  199. #TODO 报错时提示
  200. sys_y = opt_obj.current_system_y.loc[:,[y_col]]
  201. init_sys_y.append(sys_y)
  202. #TODO 放在最后可能不太合适,最好能指定
  203. final_result = result + init_sys_y
  204. return final_result