Как сбалансировать химическое уравнение в Python 2.7 с помощью матриц

У меня есть задание в колледже, где я должен сбалансировать следующее уравнение:

NaOH + H2S04 -> Na2S04 + H20

мои познания в Python и программировании в целом на данный момент крайне ограничены. До сих пор я пытался использовать матрицы для решения уравнения. Похоже, я получаю решение a = b = x = y = 0. Думаю, мне нужно установить для одной из переменных значение 1 и решить для остальных трех. Я не уверен, как это сделать, у меня был поиск, похоже, что другие люди использовали более сложный код, и я не могу его уследить!

вот что у меня есть

    #aNaOH + bH2S04 --> xNa2SO4 +y H20

    #Na: a=2x
    #O: a+4b=4x+y
    #H: a+2h = 2y
    #S: b = x

    #a+0b -2x+0y = 0
    #a+4b-4x-y=0
    #a+2b+0x-2y=0
    #0a +b-x+0y=0

    A=array([[1,0,-2,0],

             [1,4,-4,-1],

             [1,2,0,-2],

             [0,1,-1,0]])

    b=array([0,0,0,0])




    c =linalg.solve(A,b)

    print c

0.0.0.0

person George Sandle    schedule 20.07.2017    source источник
comment
Поскольку ваш массив b является нулевым вектором, очевидным результатом всегда будет то, что все x равны нулю. Вам необходимо выполнить уменьшение размера.   -  person Willem Van Onsem    schedule 20.07.2017
comment
сделайте eigenvalue анализ.   -  person Ma0    schedule 20.07.2017


Ответы (4)


Проблема в том, что вы построили линейную систему, в которой b является нулевым вектором. Теперь для такой системы всегда есть прямой ответ, что все переменные тоже равны нулю. Поскольку умножение числа на ноль и добавление нулей всегда приводит к нулю.

Решением может быть присвоить переменной 1. Возьмем, к примеру, a. Если мы назначим a = 1, тогда мы получим b, x и y в зависимости от того, что a равно 1.

Итак, сейчас или линейная система:

 B  X  Y |    #
    2    |1   #  A    = 2X
-4  4  1 |1   #  A+4B = 4X+4Y
-2     2 |1   #  A+2B =    2Y
-1  1  0 |0   #     B =     X

Или поместите это в код:

>>> A = array([[0,2,0],[-4,4,1],[-2,0,2],[-1,1,0]])
>>> B = array([1,1,1,0])
>>> linalg.lstsq(A,B)
(array([ 0.5,  0.5,  1. ]), 6.9333477997940491e-33, 3, array([ 6.32979642,  2.5028631 ,  0.81814033]))

Это значит, что:

 A = 1, B = 0.5, X = 0.5, Y = 1.

Если мы умножим это на 2, мы получим:

2 NaOH + H2S04 -> Na2S04 + 2 H20

Что правильно.

person Willem Van Onsem    schedule 20.07.2017
comment
Спасибо за вашу помощь, это именно то, что я пытался сделать. - person George Sandle; 24.07.2017
comment
@ Lörd Получив два ответа на свой вопрос, вы, вероятно, захотите прочитать Что делать, если кто-то ответит. - person ImportanceOfBeingErnest; 05.08.2017

Я сослался на Решить систему линейных целочисленных уравнений в Python, которая переведен на

# Find minimum integer coefficients for a chemical reaction like
#   A * NaOH + B * H2SO4 -> C * Na2SO4 + D * H20
import sympy
import re

# match a single element and optional count, like Na2
ELEMENT_CLAUSE = re.compile("([A-Z][a-z]?)([0-9]*)")

def parse_compound(compound):
    """
    Given a chemical compound like Na2SO4,
    return a dict of element counts like {"Na":2, "S":1, "O":4}
    """
    assert "(" not in compound, "This parser doesn't grok subclauses"
    return {el: (int(num) if num else 1) for el, num in ELEMENT_CLAUSE.findall(compound)}

def main():
    print("\nPlease enter left-hand list of compounds, separated by spaces:")
    lhs_strings = input().split()
    lhs_compounds = [parse_compound(compound) for compound in lhs_strings]

    print("\nPlease enter right-hand list of compounds, separated by spaces:")
    rhs_strings = input().split()
    rhs_compounds = [parse_compound(compound) for compound in rhs_strings]

    # Get canonical list of elements
    els = sorted(set().union(*lhs_compounds, *rhs_compounds))
    els_index = dict(zip(els, range(len(els))))

    # Build matrix to solve
    w = len(lhs_compounds) + len(rhs_compounds)
    h = len(els)
    A = [[0] * w for _ in range(h)]
    # load with element coefficients
    for col, compound in enumerate(lhs_compounds):
        for el, num in compound.items():
            row = els_index[el]
            A[row][col] = num
    for col, compound in enumerate(rhs_compounds, len(lhs_compounds)):
        for el, num in compound.items():
            row = els_index[el]
            A[row][col] = -num   # invert coefficients for RHS

    # Solve using Sympy for absolute-precision math
    A = sympy.Matrix(A)    
    # find first basis vector == primary solution
    coeffs = A.nullspace()[0]    
    # find least common denominator, multiply through to convert to integer solution
    coeffs *= sympy.lcm([term.q for term in coeffs])

    # Display result
    lhs = " + ".join(["{} {}".format(coeffs[i], s) for i, s in enumerate(lhs_strings)])
    rhs = " + ".join(["{} {}".format(coeffs[i], s) for i, s in enumerate(rhs_strings, len(lhs_strings))])
    print("\nBalanced solution:")
    print("{} -> {}".format(lhs, rhs))

if __name__ == "__main__":
    main()

который работает как

Please enter left-hand list of compounds, separated by spaces:
NaOH H2SO4

Please enter right-hand list of compounds, separated by spaces:
Na2SO4 H2O

Balanced solution:
2 NaOH + 1 H2SO4 -> 1 Na2SO4 + 2 H2O
person Hugh Bothwell    schedule 20.07.2017

Вы можете использовать это решение. Он работает с любым химическим уравнением. Последний коэффициент можно вычислить со строкой, где b [i]! = 0

H2SO4 + NaOH −−> Na2SO4 + H2OH2SO4 + NaOH −−> Na2SO4 + H2O

a=np.array([[2,1,0],[1,0,-1],[4,1,-4],[0,1,-2]])
b=np.array([2,0,1,0])
x=np.linalg.lstsq(a,b,rcond=None)[0]
print(x)

y=sum(x*a[0])/b[0]   
print("y=%f"%y)

из:

[0.5 1. 0.5] y=1.000000

person Community    schedule 31.08.2018

Очень хорошо сделано. Однако, когда я протестировал этот фрагмент на следующем уравнении, взятом из учебника линейной алгебры Дэвида Лэя, в 5-м издании я получил неоптимальное решение, которое можно еще больше упростить.

На стр. 55, 1.6 Проверка упражнений, пример 7 .:

NaHCO_3 + H_3C_6H_5O_7 -> Na_3C_6H_5O_7 + H_2O + CO_2

Ваш фрагмент возвращается:

Сбалансированное решение:

15NaHCO3 + 6H3C6H5O7 -> 5Na3C6H5O7 + 10H2O + 21CO2

Правильный ответ:

3NaHCO_3 + H_3C_6H_5O_7 -> Na_3C_6H_5O_7 + 3H_2O + 3CO_2
person Mitra    schedule 21.05.2018