| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- 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
|