关键路径法是基于进度网络模型的方法,用网络图表示各项活动之间的相互关系,获得在一定工期、成本、资源约束条件下的最优进度安排。关键路径法源于美国杜邦公司对于项目管理控制成本、减少工期的研究。1959年,Kelly 和 Walker 在论文 Critical Path Planning and Scheduling 中提出了关键路径法的基本原理和方法,将该方法应用到杜邦新工厂的建设,使该工程提前两个月完工。杜邦公司采用此法安排施工和维修等计划,每年节约资金100多万美金,取得了良好的经济效益,现今是项目管理技术的核心方法。

一、关键路径法

一个大型工程或项目包括很多活动,关键路径是项目中时间最长的活动顺序,决定着可能的项目最短工期。关键路径法将项目分解成为多个独立的活动并确定每个活动的工期,然后用逻辑关系(结束-开始、结束-结束、开始-开始和开始-结束)将活动连接。首先使用正推法(Forward pass),从起点开始向后计算,依次计算每个顶点(事件)的最早开始时间 ES;然后再使用逆推法(Backward pass),从终点开始向前计算,依次计算每个顶点(事件)的最迟结束时间 LF。进而可以求出每条边(工序)的最早结束时间 EF 和最迟开始时间 LS。最早开始时间 ES 和最迟开始时间 LS 相等的边,就是关键路径上的边,对应的工序是关键工序。

1.1 作业明细表

作业(或工序)明细表是管理活动与网络技术应用的接口,其给出各工序间的前后逻辑关系的以及资源的使用情况,它是管理实践经验的结晶。网络计划图一般用在复杂的项目管理中,绘制网络计划图必须好下列准备工作。

(1)确定计划目标

网络计划的目标是多个方面和综合的目标,正是这个特点决定了网络计划的复杂性。一般按照不同的要求可以分成三类:一是时间要求;一是资源要求;一是费用要求。

(2)项目任务活动的分解

将整个项目根据技术上的需要分解为若干个互相独立的可执行的活动,通常把这种互相独立的活动称为工序或作业

(3)确定各工序的衔接顺序

明确各项工序之间的先后逻辑关系。工序之间存在执行的先后顺序关系,如需先完成A工序才能进行B工序,则称A为B紧前工序,B为A紧后工序,列出工序明细,以便建立整个项目的网络图以表示各项工序之间的相互关系。

(4)确定各个工序时间

确定各项工序所需的时间、人力、物力。一般将完成工序所需要的时间,称为工时。

后面三项准备工作一般以工序明细表或作业明细表的形式给出,所有的网络计划分析都在这个前提下执行。

1.2 工序时间参数的计算

ES:最早开始时间(Earliest Start),指某项活动能够开始的最早时间,取决于该项活动的所有紧前工作的结束时间,由顺推法计算 ES = max{EF(preceding activities)}。

EF:最早结束时间(Earliest Finish),指某项活动能够完成的最早时间。EF = ES+DU, DU为该活动的持续时间。

LF:最迟结束时间(Latest Finish),指为了保证整个项目按期完成的某项活动必须完成的最晚时间,取决于该项活动的所有紧后工作的最迟开始时间,由逆推法计算 LF = min{LS(successor activities)}。

LS:最迟开始时间(Latest Start),指为了保证整个项目按期完成的某项活动必须开始的最迟时间。LS = LF -DU,DU为该活动的持续时间。

TF:总时差(Total float time),指在不影响总工期的条件下,一个活动可以利用的机动时间。TF = LF - EF。

FF:自由时差(Free float time),指在不影响紧后工作最早开始时间的条件下,一个活动可能被延迟的时间。FF = min{ES(successor activities)} - EF。

由关键路径法得到的最早/最晚的开始/结束时间并不一定就是项目进度计划,而是把既定的参数(活动持续时间、逻辑关系、提前量、滞后量和其它制约条件)输入进度模型后所得到的结果,表明活动可以在该时段内实施。

早期关键路径法的表示方法都是箭线法(ADM,双代号网络图),随着计算机的发展,前导图(PDM,单代号网络图)逐渐成为主流方法。

1.3 关键路线的确定

总时差为零的工序就是关键工序,由他们就组成项目的关键路线。

二、关键路线法示例

案例:某项目的作业明细表

工作 紧前工作 作业时间 服务部门 工作 紧前工作 作业时间 服务部门
A - 3 IT F C 4 IT
B A 3 MKT G D,E 4 MKT
C A 3 ENG H E,F 4 PROD
D B 8 PROD I G,H 2 FIN
E B,C 5 FIN

双代号网络图

三、关键路线法的计算(python)

3.1 数据的组织与输入

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
from pandas import Timestamp dictA = {'工作名称': 'A', '紧前工作': '-', '持续时间': 3, 'partment': 'IT'}
dictB = {'工作名称': 'B', '紧前工作': 'A', '持续时间': 3, 'partment': 'MKT'}
dictC = {'工作名称': 'C', '紧前工作': 'A', '持续时间': 3, 'partment': 'ENG'}
dictD = {'工作名称': 'D', '紧前工作': 'B', '持续时间': 8, 'partment': 'PROD'}
dictE = {'工作名称': 'E', '紧前工作': 'B,C', '持续时间': 5, 'partment': 'FIN'}
dictF = {'工作名称': 'F', '紧前工作': 'C', '持续时间': 4, 'partment': 'IT'}
dictG = {'工作名称': 'G', '紧前工作': 'D,E', '持续时间': 4, 'partment': 'MKT'}
dictH = {'工作名称': 'H', '紧前工作': 'E,F', '持续时间': 2, 'partment': 'PROD'}
dictI = {'工作名称': 'I', '紧前工作': 'H,G', '持续时间': 2, 'partment': 'FIN'}
list = [dictA, dictB, dictC, dictD, dictE, dictF, dictG, dictH, dictI]

3.2 时间参数的计算

# 最早开始时间
list1 = []
for i in range(len(list)):
listtmp = {'index': '', 'value': 0}
if list[i]['紧前工作'] == '-':
list1.append(0)
continue
tmp = list[i]["紧前工作"].split(',')
for x in tmp:
index = ord(x) - ord('A')
if listtmp['index'] == '':
listtmp['index'] = index
listtmp['value'] = list1[index]
else:
if list1[ord(x) - ord('A')] > listtmp['value']:
listtmp['index'] = index
listtmp['value'] = list1[index]
list1.append(list[listtmp['index']]['持续时间'] + listtmp['value'])
print(list1) # 最早完成时间
list2 = []
for i in range(len(list1)):
list2.append(list1[i] + list[i]['持续时间'])
print(list2) # 计算工期
Tp = list2[len(list2) - 1]
# 最迟开始时间
list3 = []
# 最迟完成时间
list4 = []
for i in range(len(list) - 1, -1, -1):
if i == len(list) - 1:
list4.append(Tp)
list3.append(Tp - list[i]['持续时间'])
continue
else:
min_value = 100
for j in range(len(list) - 1, i, -1):
tmp = list[j]["紧前工作"].split(',')
if list[i]['工作名称'] in tmp:
if min_value > list3[len(list) - j - 1]:
min_value = list3[len(list) - j - 1]
list4.append(min_value)
list3.append(list4[len(list) - i - 1] - list[i]['持续时间'])
list3.reverse()
list4.reverse()
print(list3)
print(list4) # 总时差
list5 = []
for i in range(len(list)):
list5.append(list3[i] - list1[i])
print(list5) # 自由时差
list6 = []
for i in range(len(list) - 1, -1, -1):
if i == len(list) - 1:
list6.append(Tp - list2[i])
continue
else:
min_value = 100
for j in range(len(list) - 1, i, -1):
tmp = list[j]["紧前工作"].split(',')
if list[i]['工作名称'] in tmp:
if min_value > list1[j]:
min_value = list1[j]
list6.append(min_value - list2[i])
list6.reverse()
print(list6)

工序时间参数计算结果如下表所示:

Task Earliest_Start Earliest_Finish Lateat_Start Latest_Finish Total_Flote_Time Free_Flote_Time
A 0 3 0 3 0 0
B 3 6 3 6 0 0
C 3 6 6 9 3 0
D 6 14 6 14 0 0
E 6 11 9 14 3 0
F 6 10 12 16 6 1
G 14 18 14 18 0 0
H 11 13 16 18 5 5
I 18 20 18 20 0 0

3.3 关键路线的可视化——甘特图

#数据集成
df = pd.DataFrame()
df['start_num']=list1
df['end_num'] =list4
df['During']=0
df['Task']='a'
df['Department']='a'
df['Flexible']=0
for i in range(len(list)):
df.During[i] = list[i]['持续时间']
df.Task[i] = list[i]['工作名称']
df.Department[i] = list[i]['partment'] df.Flexible = 1-df.During/(df.end_num-df.start_num)
proj_start = df.start_num.min()
# days between start and end of each task
df['days_start_to_end'] = df.end_num - df.start_num
# days between start and current progression of each task
df['current_num'] = (df.days_start_to_end * (1-df.Flexible)) # 服务部门颜色
def color(row):
c_dict = {'MKT': '#E64646', 'FIN': '#E69646', 'ENG': '#34D05C', 'PROD': '#34D0C3', 'IT': '#3475D0'}
return c_dict[row['Department']] df['color'] = df.apply(color, axis=1) #甘特图
fig, ax = plt.subplots(1, figsize=(16,6))
# bars
ax.barh(df.Task, df.current_num, left=df.start_num, color=df.color)
ax.barh(df.Task, df.days_start_to_end, left=df.start_num, color=df.color, alpha=0.5)
# texts
for idx, row in df.iterrows():
ax.text(row.end_num+0.1, idx,
f"{int(row.Flexible*100)}%",
va='center', alpha=0.8)
##### LEGENDS #####
c_dict = {'MKT':'#E64646', 'FIN':'#E69646', 'ENG':'#34D05C', 'PROD':'#34D0C3', 'IT':'#3475D0'}
legend_elements = [Patch(facecolor=c_dict[i], label=i) for i in c_dict]
plt.legend(handles=legend_elements) plt.show()



*!!!注意:图中百分数数字表示各工序机动时间占比。百分比为零的就是关键工序,由关键工序组成的路线就是关键路线。

四、总结

关键路径法(CPM),是一种算法用于调度的一组项目的活动。通常与程序评估和审查技术(PERT)结合使用。关键路径是通过确定最长的依存活动范围并测量从头到尾完成这些活动所需的时间来确定的。使用关键路径法的基本技术是构建项目管理计划,其中包括以下内容:

完成项目所需的所有活动的列表(通常在工作分解结构中分类),

每个活动完成所需的时间(持续时间),

活动之间的依赖关系以及

逻辑终点,例如里程碑或可交付项。

关键路径法使用这些值来计算计划的活动到逻辑终点或项目结束的最长路径,以及每个活动可以开始和完成而不必延长项目时间的最早和最新路径。该过程确定哪些活动是“关键的”(即,在最长的路径上),哪些活动具有“全部浮动”(即,可以在不延长项目时间的情况下将其延迟)。华罗庚教授为网络计划技术在我国的引进与发展做出了巨大的贡献,他的名字也将永远闪耀在运筹优化学科的历史长河中。美国著名数学史家贝特曼称:“华罗庚是中国的爱因斯坦,足够成为全世界所有著名科学院的院士”。

参考文献

1.(Python小白的数学建模课-21.关键路径法)[https://blog.csdn.net/youcans/article/details/118754623]

2. (项目管理:关键路径法)[https://baijiahao.baidu.com/s?id=1713675917353318226&wfr=spider&for=pc]

3. 根据逻辑关系图以及双代号网络图编写求时间参数(python版)

4. Python使用Matplotlib绘制甘特图的实践

网络计划技术——关键路线法(Python)的更多相关文章

  1. 【PMP】关键路径法与关键链法

    通俗理解 关键路径法:把项目上的资源都事先全部分到每个活动上. 关键链法:每个活动不打富余,项目经理自己掌握资源,哪个成员执行过程中遇到困难,再给他单独分配资源. PMBOK定义 关键路径法:关键路径 ...

  2. python入门灵魂5问--python学习路线,python教程,python学哪些,python怎么学,python学到什么程度

    一.python入门简介 对于刚接触python编程或者想学习python自动化的人来说,基本都会有以下python入门灵魂5问--python学习路线,python教程,python学哪些,pyth ...

  3. PMBOK及PMP考试精要

    PROJECT MANAGEMENT KNOWLEDGE AREAS项目管理知识体系 2 PROJECT LIFE CYCLE / PROJECT MANAGEMENT PROCESS GROUPS项 ...

  4. 甘特图和PERT图

    gantt图又叫甘特图.进度是按时间顺序计划活动的一个列表,我们称之为Gantt图,它有以下几个关键的成分:1.横跨图顶部排列的是日历表.2.最左边的一列包含了每项任务的标识号(ID).3.左边第二列 ...

  5. 【项目管理】 项目管理术语总结 (PMP培训笔记)

    1. 项目管理简介 (1) 项目管理定义 项目管理定义 : 将 知识, 技能, 工具 与 技术 应用与项目活动, 以满足项目的要求; (2) 现代项目管理 现代项目管理与传统项目管理区别 : -- 传 ...

  6. PMBOK

    项目章程的内容1. 基于项目干系人的需求和期望提出的要求.2. 项目必须满足的业务要求或产品需求.3. 项目的目的或项目立项的理由.4. 委派的项目经理及项目经理的权限级别.5. 概要的里程碑进度计划 ...

  7. python计算平面的法向-利用协方差矩阵求解特征值和特征向量

    Obvious,最小特征值对应的特征向量为平面的法向 这个问题还有个关键是通过python求协方差矩阵的特征值和特征向量,np.linalg.eig()方法直接返回了特征值的向量和特征向量的矩阵 sc ...

  8. Python实现客观赋权法

    本文从阐述Python实现客观赋权法的四种方式: 一. 熵权法 二. 因子分析权数法(FAM) 三. 主成分分析权数法(PCA) 四. 独立性权系数法 Python实现客观赋权法,在进行赋权前,先导入 ...

  9. Python基本概念及零碎知识点

    1.python面向对象 类和对象是面向对象编程的两个主要方面.类创建一个新类型,而对象这个类的实例:这类似于你有一个int类型的变量,这存储整数的变量是int类的实例(对象)把握一点:在python ...

  10. Python之面向对象的组合、多态、菱形问题、子类中重用父类的两种方式

    一.组合 ''' 1.什么是组合 组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象 2.为何用组合 组合也是用来解决类与类直接代码冗余问题的 3.如何用组合 ''' # 继承减少代 ...

随机推荐

  1. QT动态库的创建和使用

    QT动态库的创建和使用 步骤一: 创建一个库文件 Library 步骤二:进行动态库封装方法的实现 注意事项:要注意共享类均需要包含导出的宏定义 这个宏定义和导出向导的宏定义一致 宏定义: 向导文件: ...

  2. 用bcftools将多个vcf文件合并成一个vcf文件 或将多个vcf和合并成的vcf文件拆分成单个样本的vcf文件

    1. 软件的安装 a. bcftools 的安装 b. bgzip的安装: https://blog.csdn.net/weixin_30471065/article/details/95108525 ...

  3. 关于FPGA学习的疑惑

    记录心路历程--第一次真正意义上的找工作. 最近在学习小梅哥的FPGA的过程中,总是学习着前面的东西忘着后面的,进行了过一次复习,我准备是在每个章节学完之后,再复习之前的章节,可这样是真的很耗费时间. ...

  4. 如何服务好B端客户

    核心价值: 2B公司的核心价值在于服务.如何服务好客户,需要的是了解客户,与客户共赢. 一.客户信任度的建立 服务:不是口头说说,是要落地与实践. 对于客户的承诺至关重要,承诺的时间点.承诺的事情要保 ...

  5. CentOS7安装 Redis5 单实例

    1.下载redis下载地址在:redis.io比如把Redis安装到/usr/local/soft/ cd /usr/local/soft/ wget http://download.redis.io ...

  6. Linux env commands

    1.新机新增root 密码 sudo passwd root 2.新增用户密码 sudo passwd YOUR_USER_NAME NEW PW: NEW PW: 3.SSH Server sudo ...

  7. loadrunner之录制脚本

    LoadRunner是一款性能测试软件,通过模拟真实的用户行为,通过负载.并发和性能实时监控以及完成后的测试报告,分析系统可能存在的瓶颈,LoadRunner最为有效的手段之一应该就是并发控制,通过在 ...

  8. You need to run build with JDK or have tools.jar on the classpath.If this occures during eclipse build make sure you run eclipse under JDK as well 错误

    我打开项目报错是这样的  pom.xml jdk配置什么的都是好的    但是还是报错 解决错误 : 1.打开你eclipse的根目录,找到eclipse.ini  这个文件夹打开 2.打开是这个样子 ...

  9. typescript 的动态引入组件

    环境: Arco Pro + Vue3 vite自身对动态字符串形式的组件引入是有限制的, 以下写法会报错 官方文档中也对此有做说明, 只能通过固定形式去引用 以下形式不会报错, 但这种固定格式的局限 ...

  10. Jsp 总结

    JSP中的include的两种用法 1.两种用法 <@inlcude file ="header.jsp"/> 此时引入的是静态的jsp文件,它将引入的jsp中的源代码 ...