NetworkX系列教程(10)-算法之三:关键路径问题
重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定先把图论中常用算法弄个明白在写这部分.
图论常用算法看我的博客:
下面我将使用NetworkX实现上面的算法,建议不清楚的部分打开两篇博客对照理解.
我将图论的经典问题及常用算法的总结写在下面两篇博客中:
图论---问题篇
图论---算法篇
目录:
* 11.3关键路径算法(CPA)
注意:如果代码出现找不库,请返回第一个教程,把库文件导入.
11.3关键路径算法(CPA)
以下代码从这里复制,由于版本问题,将代码中的:nx.topological_sort(self, reverse=True)改为list(reversed(list(nx.topological_sort(self))))
- import networkx as nx
- import matplotlib.pyplot as plt
- from matplotlib.font_manager import *
- #定义自定义字体,文件名从1.b查看系统中文字体中来
- myfont = FontProperties(fname='/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc')
- #解决负号'-'显示为方块的问题
- matplotlib.rcParams['axes.unicode_minus']=False
- class CPM(nx.DiGraph):
- def __init__(self):
- super().__init__()
- self._dirty = True
- self._critical_path_length = -1
- self._criticalPath = None
- def add_node(self, *args, **kwargs):
- self._dirty = True
- super().add_node(*args, **kwargs)
- def add_nodes_from(self, *args, **kwargs):
- self._dirty = True
- super().add_nodes_from(*args, **kwargs)
- def add_edge(self, *args): # , **kwargs):
- self._dirty = True
- super().add_edge(*args) # , **kwargs)
- def add_edges_from(self, *args, **kwargs):
- self._dirty = True
- super().add_edges_from(*args, **kwargs)
- def remove_node(self, *args, **kwargs):
- self._dirty = True
- super().remove_node(*args, **kwargs)
- def remove_nodes_from(self, *args, **kwargs):
- self._dirty = True
- super().remove_nodes_from(*args, **kwargs)
- def remove_edge(self, *args): # , **kwargs):
- self._dirty = True
- super().remove_edge(*args) # , **kwargs)
- def remove_edges_from(self, *args, **kwargs):
- self._dirty = True
- super().remove_edges_from(*args, **kwargs)
- #根据前向拓扑排序算弧的最早发生时间
- def _forward(self):
- for n in nx.topological_sort(self):
- es = max([self.node[j]['EF'] for j in self.predecessors(n)], default=0)
- self.add_node(n, ES=es, EF=es + self.node[n]['duration'])
- #根据前向拓扑排序算弧的最迟发生时间
- def _backward(self):
- #for n in nx.topological_sort(self, reverse=True):
- for n in list(reversed(list(nx.topological_sort(self)))):
- lf = min([self.node[j]['LS'] for j in self.successors(n)], default=self._critical_path_length)
- self.add_node(n, LS=lf - self.node[n]['duration'], LF=lf)
- #最早发生时间=最迟发生时间,则判断该节点为关键路径上的关键活动
- def _compute_critical_path(self):
- graph = set()
- for n in self:
- if self.node[n]['EF'] == self.node[n]['LF']:
- graph.add(n)
- self._criticalPath = self.subgraph(graph)
- @property
- def critical_path_length(self):
- if self._dirty:
- self._update()
- return self._critical_path_length
- @property
- def critical_path(self):
- if self._dirty:
- self._update()
- return sorted(self._criticalPath, key=lambda x: self.node[x]['ES'])
- def _update(self):
- self._forward()
- self._critical_path_length = max(nx.get_node_attributes(self, 'EF').values())
- self._backward()
- self._compute_critical_path()
- self._dirty = False
- if __name__ == "__main__":
- #构建graph
- G = CPM()
- G.add_node('A', duration=5)
- G.add_node('B', duration=2)
- G.add_node('C', duration=4)
- G.add_node('D', duration=4)
- G.add_node('E', duration=3)
- G.add_node('F', duration=7)
- G.add_node('G', duration=4)
- G.add_edges_from([
- ('A', 'B'),
- ('A', 'C'),
- ('C','D'),
- ('C','E'),
- ('C','G'),
- ('B','D'),
- ('D','F'),
- ('E','F'),
- ('G','F'),
- ])
- #显示graph
- nx.draw_spring(G,with_labels=True)
- plt.title('AOE网络',fontproperties=myfont)
- plt.axis('on')
- plt.xticks([])
- plt.yticks([])
- plt.show()
- print('关键活动为:')
- print(G.critical_path_length, G.critical_path)
- G.add_node('D', duration=2)
- print('\n修改D活动持续时间4为2后的关键活动为:')
- print(G.critical_path_length, G.critical_path)

从graph中可以知道,有两条关键路径,分别是:A->C->G->F和A->C->D->F,长度都是20.
输出:
关键活动为: 20 ['A', 'C', 'D', 'G', 'F']
修改D活动持续时间4为2后的关键活动为: 20 ['A', 'C', 'G', 'F']
关键活动为: ['A', 'C', 'D', 'G', 'F'],可以构成两条边.D活动持续时间4为2后,关键路径变化.
NetworkX系列教程(10)-算法之三:关键路径问题的更多相关文章
- NetworkX系列教程(10)-算法之五:广度优先与深度优先
小书匠Graph图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定先把图 ...
- NetworkX系列教程(10)-算法之四:拓扑排序与最大流问题
小书匠Graph图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定先把图 ...
- NetworkX系列教程(10)-算法之二:最小/大生成树问题
小书匠 Graph 图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定 ...
- NetworkX系列教程(10)-算法之一:最短路径问题
小书匠Graph图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定先把图 ...
- NetworkX系列教程(9)-线性代数相关
小书匠 Graph 图论 学过线性代数的都了解矩阵,在矩阵上的文章可做的很多,什么特征矩阵,单位矩阵等.grpah存储可以使用矩阵,比如graph的邻接矩阵,权重矩阵等,这节主要是在等到graph后 ...
- NetworkX系列教程(2)-graph生成器
小书匠Graph图论 本节主要讲解如何快速使用内置的方法生成graph,官方的文档在这里,里面包含了networkX的所有graph生成器,下面的内容只是我节选的内容,并将graph画出来而已. 声明 ...
- NetworkX系列教程(1)-创建graph
小书匠Graph图论 研究中经常涉及到图论的相关知识,而且常常面对某些术语时,根本不知道在说什么.前不久接触了NetworkX这个graph处理工具,发现这个工具已经解决绝大部分的图论问题(也许只是我 ...
- HTML5游戏开发系列教程10(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-10/ 最后我们将继续使用canvas来进行HTML5游戏开发系列 ...
- Python Twisted系列教程10:增强defer功能的客户端
作者:dave@http://krondo.com/an-introduction-to-asynchronous-programming-and-twisted/ 译者:杨晓伟(采用意译) 可以从这 ...
随机推荐
- 基于openfire的IM即时通讯软件开发
openfire:http://www.igniterealtime.org/ Xmpp:http://xmpp.org/ IOS(xmppframework):https://github.com/ ...
- 《一头扎进》系列之Python+Selenium框架设计篇5 - 价值好几K的框架,哎呦!这个框架还真有点料啊!!!
1. 简介 其实,到前面这一篇文章,简单的Python+Selenium自动化测试框架就已经算实现了.接下来的主要是介绍,unittest管理脚本,如何如何加载执行脚本,再就是采用第三方插件,实现输出 ...
- 通过 Kubeadm 安装 K8S 与高可用,版本1.13.4
环境介绍: CentOS: 7.6 Docker: 18.06.1-ce Kubernetes: 1.13.4 Kuberadm: 1.13.4 Kuberlet: 1.13.4 Kuberctl: ...
- iOS 内存管理的一点小问题
现在大家的项目应该基本都是ARC了,如果还是MRC的话,赶紧转换到ARC吧!最近被临时拉过去开发iPad,由于项目原因,还是使用的MRC.今天在调部分界面的时候,发现一段代码,我怎么看都怎么觉得怪怪的 ...
- poi 读取word 遍历表格和单元格中的图片
背景 项目需要解析word表格 需要批量导入系统,并保存每行信息到数据库 并且要保存word中的图片, 并保持每条信息和图片的对应关系 一行数据可能有多条图片 解决办法 没有找到现成的代码,怎么办呐? ...
- Android笔记(三十) Android中线程之间的通信(二)Handler消息传递机制
什么是Handler 之前说过了,Android不允许主线程(MainThread)外的线程(WorkerThread)去修改UI组件,但是又不能把所有的更新UI的操作都放在主线程中去(会造成ANR) ...
- Poj-3286- How many 0's? - 【基础数位DP】
How many 0's? Description A Benedict monk No.16 writes down the decimal representations of all natur ...
- Jmeter性能测试NoHttpResponseException (the target server failed to respond)
采用JMeter做Http性能测试时,在高并发请求的情况下,服务器端并无异常,但是Jmeter端报错NoHttpResponseException (the target server failed ...
- 用来遍历map集合的方法
map集合是以键值对进行存储值的,所以遍历map集合无非就是获取键和值,根据实际需求,进行获取键和值. 1.无非就是通过map.keySet()获取到值,然后根据键获取到值. for(String s ...
- 大数据之路week06--day03(jdk8新特性 Lambda表达式)
为什么使用Lambda表达式?(做为初学者接触这个新的语法,会很懵逼,说道理,我在接触到这一块的时候,语法规则我看到了也很懵逼,因为这个和逻辑的关系不是很大,但就是作为一种新的语法出现,一时间很难接受 ...