parse.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import re
  2. import numpy as np
  3. import pandas as pd
  4. def parse_constrains(constrains:list,data:pd.DataFrame) -> list:
  5. """
  6. # 解析约束字符中的特殊符号,生成可以执行的约束条件
  7. 特殊符号:
  8. - [abc] 表示模型初始值,同时包含模型的输入和输出
  9. - <1~10> 表示多个点位
  10. Parameters
  11. ----------
  12. constrains : list
  13. 原始的约束条件
  14. data : pd.DataFrame
  15. 约束条件对应的数据
  16. Returns
  17. -------
  18. list
  19. 解析后的约束
  20. Raises
  21. ------
  22. Exception
  23. - 当约束条件不以“<0”结尾
  24. - 约束条件包含多余的'#'
  25. - 未从数据中找到指定的变量
  26. """
  27. if constrains is None:
  28. return None
  29. if data.columns.has_duplicates:
  30. col = data.columns
  31. dup_col = col[col.duplicated()]
  32. raise Exception(f'约束的变量中存在重复名称,需检查系统模型的输入及输出,以及外部变量{dup_col}')
  33. constrains = multiple_constrains(constrains)
  34. parsed_con = []
  35. for con in constrains:
  36. # 将注释从文本中移除
  37. con = con.replace(' ','')
  38. chinese_str = r'\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b'
  39. all_comment = re.findall(f'#[\w{chinese_str}]+#',con)
  40. for comment in all_comment:
  41. con = con.replace(comment,'')
  42. if '#' in con:
  43. raise Exception(f'检测到多余的符号"#", 检查约束条件是否正确( {con} )')
  44. # 校验约束合规性
  45. if con[-2:] != '<0':
  46. raise Exception(f'检测到无效的约束条件{con},约束条件应以<0结尾,修改成"{con}<0"')
  47. con = con.replace('<0','')
  48. # 解析约束中的数值 (大小写敏感)
  49. current_var = re.findall('\[(\w+)\]',con)
  50. for var in current_var:
  51. # 检查字段是否存在于数据中
  52. current_data = data.reset_index(drop=True)
  53. current_col = current_data.columns.to_list()
  54. if var not in current_col:
  55. raise Exception(f'系统模型的输入和输出中未能找到{var},以下是当前系统模型的参数{current_col}')
  56. current_value = current_data.at[0,var]
  57. if np.isnan(current_value):
  58. raise Exception(f'约束变量{var}的约束值为缺失值,请检查系统模型的输出')
  59. con = con.replace(f'[{var}]',str(current_value))
  60. parsed_con.append(con)
  61. return parsed_con
  62. def multiple_constrains(constrains:list):
  63. result_constrains = []
  64. for con in constrains:
  65. num_range = list(set(re.findall('<\d+~\d+>',con)))
  66. if len(num_range) == 0:
  67. result_constrains.append(con)
  68. continue
  69. elif len(num_range) > 1:
  70. raise Exception('检查到存在多个range模式')
  71. num_start,num_end = re.findall('<(\d+)~(\d+)>',num_range[0])[0]
  72. num_start = int(num_start)
  73. num_end = int(num_end)
  74. for i in range(num_start,num_end+1):
  75. result_constrains.append(con.replace(num_range[0],str(i)))
  76. return result_constrains