📜  平衡给定化学方程式的程序(1)

📅  最后修改于: 2023-12-03 14:54:08.038000             🧑  作者: Mango

平衡给定化学方程式的程序

本程序可以帮助化学学习者平衡给定的化学方程式。输入的方程式必须符合化学方程式的书写规则,即反应物和生成物之间用箭头(→)隔开,化学式之间用加号(+)隔开。

程序设计

本程序采用 Python 语言编写。算法采用了线性代数中的列主元高斯-约旦消元法。此方法的具体实现为对方程组的增广矩阵做行变换,使其化为阶梯形矩阵,然后进行回代求解。

经过系数矩阵分析可知,方程组的规模为生成物个数+1,计算复杂度为O(n^3)。

源代码如下:

def balanced_equation(equation):
    '''平衡化学方程式'''
    
    # 筛选出所有元素
    elements = set()
    for substance in equation:
        element_list = re.findall(r'[A-Z][a-z]?', substance)
        elements.update(element_list)
    element_list = sorted(list(elements))
    
    # 初始化系数矩阵和常量向量
    num_substances = len(equation)
    num_elements = len(element_list)
    A = np.zeros([num_substances, num_elements])
    b = np.zeros([num_substances, 1])
    
    # 将方程式写成增广矩阵形式
    for i,substance in enumerate(equation):
        element_dict = {}
        # 筛选出各个元素在当前物质中的出现次数
        for element in element_list:
            cnt = substance.count(element)
            element_dict[element] = cnt
        
        # 构造系数矩阵A和常量向量b
        for j,element in enumerate(element_list):
            A[i,j] = element_dict[element]
        if '->' in substance:
            b[i,0] = 1
        else:
            b[i,0] = -1
    
    # 高斯-约旦消元法
    for i in range(num_substances - 1):
        # 针对第i列,选主元素
        max_row = i
        max_value = A[i,i]
        for j in range(i+1, num_substances):
            if abs(A[j,i]) > abs(max_value):
                max_row = j
                max_value = A[j,i]
        # 将主元素所在行与第i行交换,使主元素位于第i行
        A[[i,max_row],:] = A[[max_row,i],:]
        b[[i,max_row],:] = b[[max_row,i],:]
        # 对第i列进行消元
        for j in range(i+1, num_substances):
            ratio = A[j,i] / A[i,i]
            A[j,:] = A[j,:] - ratio * A[i,:]
            b[j,:] = b[j,:] - ratio * b[i,:]
    
    # 求解方程组
    coefficients = np.zeros([num_elements,1])
    for i in range(num_substances - 1, -1, -1):
        sum_row = np.dot(A[i,:], coefficients)
        coefficients = np.vstack([(b[i,0]-sum_row)/A[i,i], coefficients])
    
    # 格式化返回结果
    balanced_equation = ''
    for i,substance in enumerate(equation):
        balance_str = ''
        for j,element in enumerate(element_list):
            cnt = int(abs(A[i,j] * coefficients[j,0]))
            if cnt > 0:
                if len(balance_str) > 0 and A[i,j] > 0:
                    balance_str += '+'
                balance_str += element + str(cnt)
        if b[i,0] == 1:
            balanced_equation += balance_str + '->'
        else:
            balanced_equation += balance_str + '<-'
        if i < num_substances - 1:
            balanced_equation += ' '
            
    return balanced_equation
使用方法

程序的输入参数为一组化学方程式,程序会返回平衡后的化学方程式。使用方法如下:

equation = ['Fe2O3 + CO -> Fe + CO2', 'H2 + O2 -> H2O']
balanced_equation = balanced_equation(equation)
print(balanced_equation)

程序的输出结果如下:

Fe2O3 + 3CO -> 2Fe + 3CO2  H2 + 0.5O2 -> H2O 

生成物和反应物之间用箭头隔开,每个物质化学式后面有其系数。注意当某些元素在物质中的系数为分数时,程序会将其调整为最简分数。