你好获取登录信息中




首页 主站 文章列表 分类列表
查看文章返回文章列表

简单的化学反应自动配平

发布时间:2020-08-15 15:35:46 by:
最后更新时间:2020-08-21 16:47:14 by:



前言

高中时有做化学反应方程自动配平的想法,当时其实已经想到了用方程求解,当时并没有好的方法去求解,所以鸽了。之后也没有再学习化学了,所以就也没怎么想过这事了,前几天忽然想起这事来于是就着手做了一个,用了线性代数的东西,不过也不是很难所以讲讲原理.成品测试地址点我

化学反应的原子守恒

对于一个化学反应来说,无论如何反应,反应方程两边的各种原子数目都是相同的,例:

2KMnO4=加热=K2Mn04+MnO2+O2↑

左侧有2个K,右侧就一定也有2个,左右2个Mn,右侧也是2个,左侧8个O,右侧也是8个。

如果我们依次设这4种分子前面的系数为x1、x2、x3和x4的话,则有:

x1KMnO4=加热=x2K2Mn04+x3MnO2+x4O2↑

然后得到方程组:

  1. x1=x2*2 ①(K守恒)
  2. x1=x2+x3 ②(Mn守恒)
  3. x1*4=x2*4+x3*2+x4*2 ③(O守恒)

通过解方程的方式不难判断出各项两两之间的比值,我们只要求出最简整数比就可以得到各部分的系数了。

比如②式减①式可以得到0=x3-x2

  1. x3=x2 ④

将①式和④式带入③式可以得到x2*2*4=x2*4+x2*2+x4*2,即:

  1. x4=x2

然后取x2=1得

  1. x1=2 x2=1 x3=1 x4=1

从而方程得到配平

通用的线性方程组求解——线性代数

上面的计算是需要通过观察的方式来解方程,但是计算机只是机器,它并不能做到真正意义上的观察(所谓机器学习,只是通过大量训练数据,判断出每个条件下输出啥的可能性最高,这个过程跟人的条件反射类似,所以也叫神经网络,但实际上机器并不会去理解这个条件的含义以及这么做会发生啥),因此我们需要找到一种通用的解方程的方式。

首先我们可以看到,我们的方程中有些缺少的项,如果我们要做通用的计算方法,这些空出来的部分显然会对我们造成困扰,所以我们需要把这些确实的项补上,于是得到

  1. x1*1=x2*2+x3*0+x4*0
  2. x1*1=x2*1+x3*1+x4*0
  3. x1*4=x2*4+x3*2+x4*2

好了,这就是一个一个比较标准的形式了,但是为了统一处理,我们还需要进一步转换,将所有数移动到方程的一侧,让另一次等于0

  1. x1*(-1)+x2*2+x3*0+x4*0+0=0
  2. x1*(-1)+x2*1+x3*1+x4*0+0=0
  3. x1*(-4)+x2*4+x3*2+x4*2+0=0

好了,这个方程就整理结束了,它的每个式子都是一模一样的形式的,每一项也都是一样的一个系数了。但是呢,计算机仍然不能理解x1-xn这种未知变量,反正我们计算的时候要的也就是前面那个系数而已,未知变量是啥符号本身我们不需要关心,所以我们也把它省略掉于是得到这样一个东西

  1. -1 2 0 0 0
  2. -1 1 1 0 0
  3. -4 4 2 2 0

好了,这就包含了我们方程中的所有信息了,但是,它只是一堆数字,处理数字自然就是计算机拿手的活了。而这个东西就是一个矩阵。所谓线性代数,本质上核心就是把多元一次方程(一次方程也就是所谓线性,当其中一个未知量变化时,函数图像是一条直线,所以叫做线性,而二次方程或者其他的方程对应函数图像是抛物线或者其他曲线)。接下来我们就是要解这个方程了。

我们正常解方程,除了直接把已知的变量表达式带进去以外,还有两式相加减、等式两边同时乘以某个数的操作,那么这些操作在线性代数中仍然存在。比如我们让第一个式子方程两边同时乘-1,可以得到:

  1. 1 -2 0 0 0 x1*(+1)+x2*(-2)+x3*0+x4*0+0=0
  2. -1 1 1 0 0 x1*(-1)+x2*(+1)+x3*1+x4*0+0=0
  3. -4 4 2 2 0 x1*(-4)+x2*(+4)+x3*2+x4*2+0=0

这样,我们第一行式子就算处理完了,我们已经得出1个x1和其他变量的关系了,接下来,我们希望得到x2的关系,但是,这时候把x1带进来就是一个不明智的选择了,因为我需要x1的时候我会需要知道x2,然后我需要x2的时候我又得知道x1,就死循环了,因此我们接下来要得到一个不包含x1的式子。但是矩阵这个行列还是得对齐的啊,那么我们其实需要的是让x1的系数变成0就好了。第一行已经用了,那我们自然就会想选第二行来操作。第二行的x1系数是-1,那么只要我们第一行正好已经求出了一个x1的关系,那么我们为了得到0,我们就应该加上一个第一行,或者更通用一点,我现在是多了-1个第1行,那我就减去-1个第一行这样。然后得到

  1. 1 -2 0 0 0 x1*(+1)+x2*(-2)+x3*0+x4*0+0=0
  2. 0 -1 1 0 0 x1*(+0)+x2*(-1)+x3*1+x4*0+0=0
  3. -4 4 2 2 0 x1*(-4)+x2*(+4)+x3*2+x4*2+0=0

这样x2的关系就有了,并且还不包含x1了。但是这个系数是-1,我们不太满意,这会给之后的计算造成困扰,我们应该把它和x1一样变成单位数量1的表示,于是,方程两边同时乘-1得到

  1. 1 -2 0 0 0 x1*(+1)+x2*(-2)+x3*(+0)+x4*0+0=0
  2. 0 1 -1 0 0 x1*(+0)+x2*(+1)+x3*(-1)+x4*0+0=0
  3. -4 4 2 2 0 x1*(-4)+x2*(+4)+x3*(+2)+x4*2+0=0

好了,我们还有最后一行数据,同样的方法,先把里面的x1消掉(即减去-4个第一行)得到

  1. 1 -2 0 0 0 x1*(+1)+x2*(-2)+x3*(+0)+x4*0+0=0
  2. 0 1 -1 0 0 x1*(+0)+x2*(+1)+x3*(-1)+x4*0+0=0
  3. 0 -4 2 2 0 x1*(+0)+x2*(-4)+x3*(+2)+x4*2+0=0

但是这仍然不是一个满意的结果,里面包含了-4个x2,那么我们继续减去-4个第二行得到

  1. 1 -2 0 0 0 x1*(+1)+x2*(-2)+x3*(+0)+x4*0+0=0
  2. 0 1 -1 0 0 x1*(+0)+x2*(+1)+x3*(-1)+x4*0+0=0
  3. 0 0 -2 2 0 x1*(+0)+x2*(+0)+x3*(-2)+x4*2+0=0

然后除以-2让它得到一个单位的x3的表示

  1. 1 -2 0 0 0 x1*(+1)+x2*(-2)+x3*(+0)+x4*(+0)+0=0
  2. 0 1 -1 0 0 x1*(+0)+x2*(+1)+x3*(-1)+x4*(+0)+0=0
  3. 0 0 1 -1 0 x1*(+0)+x2*(+0)+x3*(+1)+x4*(-1)+0=0

好了,我们现在3行数据全部处理完毕了,如果有更多的行,我们只要按相同的方法做就行了。

但是似乎,这是一个4元方程,我们3个方程是求不出唯一解的。怎么得出反应方程的系数稍后再谈,先留着你们想想。如果你仔细观察的话就会发现这种格式下行数应该等于列数-1的时候我们才能求出xn的值,然后代入第n-1行,求出xn-1,然后一直求到x1。这个行数就是矩阵的 秩 。当矩阵的秩小于n时,我们是缺少式子的,我们能找到他们之间的关系,但是不能算出一个具体的数。只有秩等于n时才会有唯一解。

未知变量和等式关系数量相同就一定能解吗?

答案显然是不行。我们应该都有见过这个一个方程:

  1. x=y
  2. y=z
  3. z=x

似乎是有3个不重复的式子,但是仔细想想前两条其实是能推出第三条的,这条是无意义的式子,在线性代数中表现如下

  1. 1 -1 0 0
  2. 0 1 -1 0
  3. -1 0 1 0

第一二行显然不需要处理(或者说处理完结果也是一样,除以1是不会改变的,加上一个被0乘的数字也就是加0,也不会变),然后就是第三行,按我们之前的加-1个第一行。看好了,这跟第二行是不是只差个符号?我们把它用之前的方法继续处理

  1. 1 -1 0 0
  2. 0 1 -1 0
  3. 0 -1 1 0

看好了,这跟第二行是不是只差个符号?我们把它用之前的方法继续处理

  1. 1 -1 0 0
  2. 0 1 -1 0
  3. 0 0 0 0

然后就会发现这一行数据全部被消掉了,各项均为0了。那么这一行也是没有意义的,如果计算时碰到这样的行,那就应该把这一行删掉然后用下一行代替这一行的位置重新计算了。不过这里没有下一行了,所以这个方程的解也不唯一,算秩的时候也要把计算后全0的行去掉才能得出正确结论。

那方程多了会发生啥?

方程过多的情况比较少,我这也就不举例子了,但是你可以想象一下,如果多出来的行全为0,那么无伤大雅,多出来的部分被去掉就行。如果不是0我们会得到一个类似这样的矩阵:

  1. 1 a b
  2. 0 1 c
  3. 0 0 1

那么这个矩阵意味着啥呢?我们把方程还原回来就是1=0了!这显然是一个不成立的结果。这也正是因为定义了过多的方程,并且这些方程中存在冲突。例如我一边希望x=1一边希望x=2,然后代入的时候就会出现矛盾了。至于更多的方程的时候,因为矛盾已经产生,所以无法再继续进行下去了。不过做矩阵计算的时候,只要没出现矛盾(即秩大于n)就应该继续计算直到把多出来的行全部化为0或者出现矛盾。

最后看看为啥反应方程能得出唯一解

我们最后处理出来的矩阵长这样

  1. 1 -2 0 0 0
  2. 0 1 -1 0 0
  3. 0 0 1 -1 0

你仔细想想我们实际的反应方程,我们系数全部乘x不也是成立的吗?但是我们不会那样写,这只是数学上成立。实际上我们要的是一个最简比,这样解当然得不到最后的结论。同时你应该发现我们解的这个方程常数项始终是0,实际上我们可以去掉,我们只要得出xn-1=?xn就可以了。所以我们实际解的方程的矩阵是这样

  1. 1 -2 0 0
  2. 0 1 -1 0
  3. 0 0 1 -1

然后我们令x4=1;然后可以得出

  1. x3=-1*(x4*(-1))/1=1
  2. x2=-1*(x4*0+x3*(-1))/1=1
  3. x1=-1*(x4*0+x3*0+x2*(-2))/1=2

当然,如果这中间出现了分数,则应化至最简单然后给各项都乘上。另外,由于绝大多数编程语言都没有分数计算的功能,而使用小数,不仅丢失精度,也不知道分母是多少,这会给我们的计算带来许多不确定性,因此需要自己实现分数计算,包括前面的数据处理就应该使用分数(很巧我用的例子正好都是整数),加减乘除都是初中难度就不多说了,唯一复杂的是怎么样将分数化简到最简。一个简单的思路是从二者之间值较小的那个取起,然后依次减少直到为2,如果中间的数字能被分子分母同时整除就用这个数进行依次约分。另外记得负号的处理,不然会很痛苦的。

最后谈谈特殊情况

这里还有一种特殊情况,如果我们矩阵算到了这个程度(c≠0)

  1. 1 a b c
  2. 0 0 d e
  3. ? ? ? ?

那么我们显然没法通过乘法让第n行第n列(这里是n=2)的0变成1了,这时候需要将下一行拿过来计算了,如果所有的行都这样那么这个方程就会因为xn不能确定而卡住,那么这样的方程也是求不出唯一解的

评论
    还没有评论
发表评论
正在等候用户中心返回数据
杂项
。。。