修正了parser 矩阵运算还不完善

This commit is contained in:
_Karasu_ 2022-12-11 11:08:28 +08:00
parent 9eee646100
commit e8404e1f9d
3 changed files with 47 additions and 18 deletions

View File

@ -53,16 +53,22 @@ def solve_equation(eq):
row.append(0) row.append(0)
# 取出row中的最后一个元素反转后加入常数项 # 取出row中的最后一个元素反转后加入常数项
constant.append(-row.pop()) constant.append(-row.pop())
matrix.append(row)
matrix = np.mat(matrix, int) matrix = np.mat(matrix, int)
print(matrix)
print(constant)
# 求解线性方程组 # 求解线性方程组
try: try:
result = sp.linalg.solve(matrix, constant).tolist() result = np.linalg.solve(matrix, constant).tolist()
except Exception as e: except np.linalg.LinAlgError:
print(e.args[0]) # 将常数项取负,插入到矩阵的最后一列
print('无解') constant = [-x for x in constant]
return None matrix = np.insert(matrix, matrix.shape[1], constant, axis=1)
# 再次尝试求解
try:
constant = np.zeros(matrix.shape[0], int)
result = sp.linalg.solve(matrix, constant).tolist()
except Exception as e:
print('无法配平' + str(e))
return None
# 将结果写入化学方程式,最后一个生成物的系数需要计算得到 # 将结果写入化学方程式,最后一个生成物的系数需要计算得到
last_substance = eq['right'][-1] last_substance = eq['right'][-1]
@ -70,6 +76,7 @@ def solve_equation(eq):
# 计算除最后一种生成物外的所有生成物包含last_atom的系数之和 # 计算除最后一种生成物外的所有生成物包含last_atom的系数之和
sum_ = 0 sum_ = 0
index = 0 index = 0
print(result)
for each in eq['left']: for each in eq['left']:
for atom in each['atoms']: for atom in each['atoms']:
if last_atom in atom: if last_atom in atom:

View File

@ -10,10 +10,13 @@ import equation_solver
if __name__ == '__main__': if __name__ == '__main__':
while True: while True:
eq = input('请输入化学方程式:') eq = input('请输入化学方程式:')
if eq == 'exit':
break
try: try:
eq = parser.parse_equation(eq) eq = parser.parse_equation(eq)
equation_solver.solve_equation(eq) eq = equation_solver.solve_equation(eq)
print('化学方程式:', parser.format_equation(eq)) if eq is not None:
print('化学方程式:', parser.format_equation(eq))
except Exception as e: except Exception as e:
print(e.args[0]) print(e.args[0])

View File

@ -49,21 +49,30 @@ def parse_atomic_clusters(atomic_clusters):
""" """
将原子团转化为字典 将原子团转化为字典
:param atomic_clusters: 经过parse_molecule处理后的原子团 :param atomic_clusters: 经过parse_molecule处理后的原子团
(ClO)2->['(', 'Cl', 'O', ')2'] (ClO)2->['(', 'Cl', 'O', ')', '2']
:return: 原子团的字典表示 :return: 原子团的字典表示
""" """
# 去除首括号 # 去除首括号
atomic_clusters = atomic_clusters[1:] atomic_clusters = atomic_clusters[1:]
# 去除尾括号,解析尾括号后的数值作为原子团系数 # 去除尾括号,解析尾括号后的数值作为原子团系数
if atomic_clusters[-1][-1].isdigit(): if atomic_clusters[-1].isdigit():
coefficient = int(atomic_clusters[-1][-1]) coefficient = int(atomic_clusters[-1])
atomic_clusters = atomic_clusters[:-1] atomic_clusters = atomic_clusters[:-2]
elif atomic_clusters[-1] == ')': elif atomic_clusters[-1] == ')':
coefficient = 1 coefficient = 1
else: else:
raise ValueError('无效的原子团系数') raise ValueError('无效的原子团系数')
# 解析原子团 # 解析原子团
atoms = [] atoms = []
for i in range(len(atomic_clusters)):
if atomic_clusters[i].isdigit():
while atomic_clusters[i - 1] == '':
i -= 1
if i == 0:
raise ValueError('系数错误')
atomic_clusters[i - 1] += atomic_clusters[i]
atomic_clusters[i] = ''
atomic_clusters = [atom for atom in atomic_clusters if atom != '']
for atom in atomic_clusters: for atom in atomic_clusters:
atoms.append(parse_atom(atom)) atoms.append(parse_atom(atom))
return { return {
@ -86,27 +95,30 @@ def parse_molecule(molecule):
:param molecule: 化学式 :param molecule: 化学式
:return: 化学式的字典表示 :return: 化学式的字典表示
""" """
pretty_name = ''
if molecule[0].isdigit(): if molecule[0].isdigit():
coefficient = int(molecule[0]) coefficient = int(molecule[0])
pretty_name = molecule = molecule[1:] pretty_name = molecule = molecule[1:]
else: else:
coefficient = 1 coefficient = 1
pretty_name = molecule pretty_name = molecule
# 以大写字母为分隔符,分割化学式 # 以大写字母和括号为分隔符,分割化学式
molecule = re.split(r'([A-Z][a-z]*)', molecule) molecule = re.split('([A-Z][a-z]*|\(|\))', molecule)
molecule = [i for i in molecule if i != ''] molecule = [i for i in molecule if i != '']
# 将原子团提取出来单独处理 # 将原子团提取出来单独处理
atomic_clusters = [] atomic_clusters = []
for i in range(len(molecule)): for i in range(len(molecule)):
if molecule[i] == '(': if molecule[i] == '(':
j = i + 1 j = i + 1
while molecule[j][0] != ')': # 当molecule内不包含右括号
while ')' not in molecule[j]:
j += 1 j += 1
if j == len(molecule): if j == len(molecule):
raise ValueError('括号不匹配') raise ValueError('括号不匹配')
for k in range(i, j + 1): for k in range(i, j + 1):
atomic_clusters.append(molecule[k]) atomic_clusters.append(molecule[k])
if j + 1 < len(molecule) and molecule[j + 1].isdigit():
atomic_clusters.append(molecule[j + 1])
molecule[j + 1] = ''
for k in range(i, j + 1): for k in range(i, j + 1):
molecule[k] = '' molecule[k] = ''
# 如果出现单个数字,说明该数字是系数,将其追加到上一个原子/原子团(非空字符串)的后面 # 如果出现单个数字,说明该数字是系数,将其追加到上一个原子/原子团(非空字符串)的后面
@ -169,6 +181,7 @@ def format_molecule(molecule):
else: else:
return molecule['pretty_name'] return molecule['pretty_name']
def format_equation(eq): def format_equation(eq):
""" """
将化学方程式的字典表示转化为字符串需要包含系数 将化学方程式的字典表示转化为字符串需要包含系数
@ -180,3 +193,9 @@ def format_equation(eq):
left = [format_molecule(molecule) for molecule in left] left = [format_molecule(molecule) for molecule in left]
right = [format_molecule(molecule) for molecule in right] right = [format_molecule(molecule) for molecule in right]
return ' + '.join(left) + ' => ' + ' + '.join(right) return ' + '.join(left) + ' => ' + ' + '.join(right)
if __name__ == '__main__':
eq = input('测试parser请输入分子式')
parsed_eq = parse_molecule(eq)
print('解析结果:', parsed_eq)