鱼C论坛

 找回密码
 立即注册
查看: 1485|回复: 17

[已解决]求助!小白求问怎么用Python来寻找大量的化学反应式中的环路

[复制链接]
发表于 2020-5-29 22:14:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我现在有一个Excel,里面有上百的化学方程式,
大概这种形式
A+B=C+D
C=E+F
F+G=A+H
...
可以看到存在A-C-F-A的化学反应环路
求问各路大神,怎么用Python在上百个错综复杂的反应中,找出如上存在的环路?

如有大神解答,愿以酬金奉上
最佳答案
2020-5-30 12:16:50
本帖最后由 java2python 于 2020-5-30 12:24 编辑
  1. #反应方程式
  2. class  Chem_equation:
  3.     def __init__(self,left,right):
  4.         self.left = left
  5.         self.right = right
  6.     #打印方程式:a+b=c+d
  7.     def get_equation(self):
  8.         chem_equ = ""
  9.         for l in range(0,len(self.left)):
  10.             chem_equ = chem_equ + self.left[l] + "+"
  11.         chem_equ = chem_equ[0:-1] + "="
  12.         for r in range(0,len(self.right)):
  13.             chem_equ = chem_equ + self.right[r] + "+"
  14.         chem_equ = chem_equ[0:-1]
  15.         return chem_equ
  16.         
  17. #某元素是反应物的词典:(0)a+b=c+d (7)a+m=k+l 那么map中就有一条{'a':[0,7]}
  18. class React_map:
  19.     react_element = {}

  20.     @staticmethod
  21.     def ele_in_equation_left(chem_list):
  22.         for c in range(0,len(chem_list)):
  23.             chem = chem_list[c]
  24.             left = chem.left
  25.             for l in range(0,len(left)):
  26.                 element = React_map.react_element.get(left[l])
  27.                 if element == None:
  28.                     React_map.react_element.update({left[l]:[c]})
  29.                 else:
  30.                     element.append(c)

  31. #搜索节点:
  32. class Srh_node:
  33.     def __init__(self,equation_no,equafrom,routefrom):
  34.         self.equation_no = equation_no       #方程式编号
  35.         self.equafrom = equafrom             #本节点来自于方程式编号
  36.         self.routefrom = routefrom           #本节点来自于搜索队列号

  37. #初始化反应方程式列表
  38. def init_equation_list():
  39.     chem_list = []
  40.     chem_list.append(Chem_equation(['a','b'],['c','d']))
  41.     chem_list.append(Chem_equation(['c'],['e','f']))
  42.     chem_list.append( Chem_equation( ['f','g'],['a','h']))
  43.     chem_list.append(Chem_equation(['c','g'],['d','h']))
  44.     chem_list.append(Chem_equation(['d'],['m','n']))
  45.     chem_list.append(Chem_equation(['m','g'],['b','x']))
  46.     chem_list.append(Chem_equation(['s','t'],['u','v']))
  47.     return chem_list

  48. #主程序
  49. def main():
  50.     chem_list = init_equation_list()
  51.     React_map.ele_in_equation_left(chem_list)
  52.     #debug :打印方程式列表
  53.     print("#################方程式列表")
  54.     for i in range(0,len(chem_list)):
  55.         print("<%d>%s" % (i,chem_list[i].get_equation()))
  56.     #debug test:打印元素在左侧的方程式:元素,方程式列表
  57.     print("#################元素在左侧的方程式:元素,方程式列表")
  58.     for item in React_map.react_element.items():
  59.         print(item[0],item[1])

  60.     #搜索开始
  61.     chem_list_visted = {}    #已访问节点
  62.     routes = []       #搜索路线,列表中保存搜索节点
  63.     circles = []      #构成环路路线:保存字符串:方程式0->方程式4->方程式5->方程式0
  64.     srh_node = Srh_node(0,0,0)
  65.     routes.append(srh_node)
  66.     #上次搜索指针,当前搜索指针(指向搜索队列)
  67.     # 搜到的节点加入一个,当前搜索指针就加1,当前搜索指针>上次搜索指针意味搜索没有结束
  68.     last_routes_ptr = 0
  69.     cur_routes_ptr = 1
  70.     #第一次从初节点开始,不断发展,知道发展不出新节点
  71.     while cur_routes_ptr > last_routes_ptr:
  72.         cur_routes_ptr_tmp = cur_routes_ptr
  73.         #从上次搜索指针->当前搜索节点,也就是上次新发展的节点再发展
  74.         for i in range(last_routes_ptr,cur_routes_ptr_tmp):
  75.             #从队列取出一个节点(方程式)
  76.             srh_node = routes[i]
  77.             #该方程式取出右侧元素,对所有右侧元素循环
  78.             right = chem_list[srh_node.equation_no].right
  79.             for r in range(0,len(right)):
  80.                 #找出右侧元素在方程式左侧的方程式
  81.                 equations = React_map.react_element.get(right[r])
  82.                 if equations != None:
  83.                     #把这些方程式中没有访问过的,全部加入队列
  84.                     for e in range(0,len(equations)):
  85.                         if chem_list_visted.get(equations[e]) == None:
  86.                             if routes[0].equation_no == equations[e]:
  87.                                 #回到初始节点
  88.                                 circle_node = srh_node
  89.                                 route_str = "->方程式" + str(circle_node.equation_no) + "->方程式0"
  90.                                 while circle_node.equafrom != routes[0].equation_no:
  91.                                     circle_node = routes[circle_node.routefrom]
  92.                                     route_str = "->方程式" + str(circle_node.equation_no) + route_str
  93.                                 route_str = "方程式0" + route_str
  94.                                 circles.append(route_str)
  95.                             else:
  96.                                 #非初始节点,且没有被访问过
  97.                                 chem_list_visted.update({equations[e]:0})
  98.                                 sub_node = Srh_node(equations[e],srh_node.equation_no,i)
  99.                                 routes.append(sub_node)
  100.                                 cur_routes_ptr += 1
  101.         #搜索队列/上次搜索指针更新
  102.         last_routes_ptr = cur_routes_ptr_tmp
  103.     #debug test:打印所有从起点开始发展出来的两个节点之间连线
  104.     print("#################所有从起点开始发展出来的两个节点之间连线")
  105.     for r in range(0,len(routes)):
  106.         srh_node = routes[r]
  107.         no = srh_node.equation_no
  108.         print("<%d:%s>来自于方程式编号:<%d:%s>" % (no,chem_list[no].get_equation(),srh_node.equafrom,chem_list[srh_node.equafrom].get_equation()))
  109.     #打印所有构成环路的线路
  110.     print("#################所有构成环路的线路")
  111.     for c in range(0,len(circles)):
  112.         print(circles[c])
  113. main()
复制代码

结果(只是以方程式0为起始点的一个列子,如果需要找出其他环路,那么再加一个外层循环:起始点就要遍历所有方程,
另外搜索中为了避免打转,标记了已访问节点,那么有些环路被忽视了:比如0->1->3,和0->1->2->3,因为第二条线路到3节点晚了,所有被忽视了):
#################方程式列表
<0>a+b=c+d
<1>c=e+f
<2>f+g=a+h
<3>c+g=d+h
<4>d=m+n
<5>m+g=b+x
<6>s+t=u+v
#################元素在左侧的方程式:元素,方程式列表
a [0]
b [0]
c [1, 3]
f [2]
g [2, 3, 5]
d [4]
m [5]
s [6]
t [6]
#################所有从起点开始发展出来的两个节点之间连线
<0:a+b=c+d>来自于方程式编号:<0:a+b=c+d>
<1:c=e+f>来自于方程式编号:<0:a+b=c+d>
<3:c+g=d+h>来自于方程式编号:<0:a+b=c+d>
<4:d=m+n>来自于方程式编号:<0:a+b=c+d>
<2:f+g=a+h>来自于方程式编号:<1:c=e+f>
<5:m+g=b+x>来自于方程式编号:<4:d=m+n>
#################所有构成环路的线路
方程式0->方程式1->方程式2->方程式0
方程式0->方程式4->方程式5->方程式0
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-5-29 22:17:19 | 显示全部楼层
第一次用这个论坛,怎么设置酬金呀,要是有大神解答,可以直接WX联系
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-29 22:34:04 | 显示全部楼层
java2python 发表于 2020-5-29 22:19
没明白题目意思:
什么叫环路,
A+B=C+D

我主要是想找出,一系列反应中,某一个物质A,经历了n个方程式后,又回到原来的形态,比如A变成了C,C又变成了F,F又变成了A
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-31 13:18:33 | 显示全部楼层
java2python 发表于 2020-5-30 12:16
结果(只是以方程式0为起始点的一个列子,如果需要找出其他环路,那么再加一个外层循环:起始点就要遍历 ...

大神,你好,我刚看到你回的帖子,太完美了!
方便加个微信吗?我好像是账号等级不够,没法私聊
请问怎么再外层加个循环,让七点遍历所有方程呀
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-2 14:47:01 | 显示全部楼层
java2python 发表于 2020-5-30 12:16
结果(只是以方程式0为起始点的一个列子,如果需要找出其他环路,那么再加一个外层循环:起始点就要遍历 ...


大神,能帮我理解下第81行吗?我感觉srh_node是类Srh_node的一个实例,routes是刚创建的空列表,routes【i】是这个列表的第i个元素, 那  srh_node = routes[i]怎么理解呀?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-4-2 02:05

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表