import re import numpy as np import pandas as pd def parse_constrains(constrains:list,data:pd.DataFrame) -> list: """ # 解析约束字符中的特殊符号,生成可以执行的约束条件 特殊符号: - [abc] 表示模型初始值,同时包含模型的输入和输出 - <1~10> 表示多个点位 Parameters ---------- constrains : list 原始的约束条件 data : pd.DataFrame 约束条件对应的数据 Returns ------- list 解析后的约束 Raises ------ Exception - 当约束条件不以“<0”结尾 - 约束条件包含多余的'#' - 未从数据中找到指定的变量 """ if constrains is None: return None if data.columns.has_duplicates: col = data.columns dup_col = col[col.duplicated()] raise Exception(f'约束的变量中存在重复名称,需检查系统模型的输入及输出,以及外部变量{dup_col}') constrains = multiple_constrains(constrains) parsed_con = [] for con in constrains: # 将注释从文本中移除 con = con.replace(' ','') chinese_str = r'\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b' all_comment = re.findall(f'#[\w{chinese_str}]+#',con) for comment in all_comment: con = con.replace(comment,'') if '#' in con: raise Exception(f'检测到多余的符号"#", 检查约束条件是否正确( {con} )') # 校验约束合规性 if con[-2:] != '<0': raise Exception(f'检测到无效的约束条件{con},约束条件应以<0结尾,修改成"{con}<0"') con = con.replace('<0','') # 解析约束中的数值 (大小写敏感) current_var = re.findall('\[(\w+)\]',con) for var in current_var: # 检查字段是否存在于数据中 current_data = data.reset_index(drop=True) current_col = current_data.columns.to_list() if var not in current_col: raise Exception(f'系统模型的输入和输出中未能找到{var},以下是当前系统模型的参数{current_col}') current_value = current_data.at[0,var] if np.isnan(current_value): raise Exception(f'约束变量{var}的约束值为缺失值,请检查系统模型的输出') con = con.replace(f'[{var}]',str(current_value)) parsed_con.append(con) return parsed_con def multiple_constrains(constrains:list): result_constrains = [] for con in constrains: num_range = list(set(re.findall('<\d+~\d+>',con))) if len(num_range) == 0: result_constrains.append(con) continue elif len(num_range) > 1: raise Exception('检查到存在多个range模式') num_start,num_end = re.findall('<(\d+)~(\d+)>',num_range[0])[0] num_start = int(num_start) num_end = int(num_end) for i in range(num_start,num_end+1): result_constrains.append(con.replace(num_range[0],str(i))) return result_constrains