资讯动态

网络计划技术详解:关键路径法、PERT与Python自动计算

发布时间:2026/10/18 12:57:53 来源:尧图企业网站定制
简介项目管理中网络计划技术的教学课件适合建筑施工组织与管理、工程管理及相关专业师生使用。内容完整覆盖网络计划基本概念、双代号网络图与单代号网络图的符号构成与绘制规则结合箭线、节点、虚工作、紧前/紧后/平行工作等关键知识点并强调虚工作仅表示逻辑关系、不消耗时间与资源同时进一步讲解关键线路、关键路径法CPM、计划评审技术PERT以及网络计划优化方法便于学习者掌握工期计算、进度控制和资源调配思路。资源为单个pptx演示文稿压缩包大小3.08MB页面围绕“概述—双代号—单代号—时标网络图—优化—应用”组织配有大量网络图示例和进度计划示意可直接用于课堂讲解和自学复习。已有46人学习可作为项目管理入门、施工进度计划课程及工程进度控制实务的实用辅助资料。1. 网络计划技术甘特图算不出的工期它用一张网算清楚网络计划技术是项目管理里用网络图表达活动逻辑、计算关键路径的一套方法代表工具就是关键路径法CPM和计划评审技术PERT。用甘特图排进度时你能看到每项任务什么时候开始、持续多久但看不到它和其他任务之间的牵制关系到底有多深一项任务晚五天项目会不会晚五天甘特图回答不了网络计划技术能。它把活动、依赖、工期变成一张有向网络通过正推和逆推算出每个活动的最早最晚时间最终找到决定项目总工期的关键路径。计划工程师、项目经理、生产排程人员都值得掌握尤其是面对几十个活动以上的排程场景这套方法比拍脑袋靠谱得多。2. 先把地基打牢工作分解与四种逻辑关系怎么定2.1 工作分解到什么粒度才够用网络计划的第一步不是画网络图而是把项目拆成一个个活动。这一步做不好后面全是空中楼阁。我见过不少排程翻车案例根源不在算法而在活动拆得不对。拆太细的典型表现把操作步骤当成活动比如“打开软件”“导出报表”“发邮件确认”这种任务清单级别的条目。一个真实项目拆出几百个节点看起来非常专业实际上谁也没法维护。任何一个细节点延期整个网络图都要重新推一遍数据录入和检查的时间比做计划本身还长。拆太粗的典型表现一个活动横跨两周内部包含多个前后依赖的环节。这种活动在网络图上只有一个框实际上它内部还有自己的顺序强行赋一个工期后关键路径计算基本失真。我判断活动粒度是否合适一般用四个标准缺一个就要重新拆活动结束时有明确的交付物或可验证的结果有单一责任人或责任团队工期可以被估计且单活动工期不小于半天它至少和另一个活动之间存在依赖关系。实际经验里我习惯用“半天”做底线。比半天还短的任务直接合并到相邻活动里。这么做不是为了偷懒而是因为网络计划技术的目标是把大局算清楚不是做任务清单。活动粒度在 5 到 20 个之间手工画图和计算都还管得住超过 30 个活动建议直接上软件或用脚本计算后面会给出一个可用的脚本模板。2.2 四种逻辑关系FS / SS / FF / SF 怎么选网络图里的边不是简单的箭头而是活动之间的逻辑关系。四类关系里 FS 占据绝大多数其余三类虽然少见但用对的时候价值很大。FS完成到开始只有 A 完成了B 才能开始。比如“模板安装完成才能浇筑混凝土”这是最符合直觉的依赖。SS开始到开始A 一开始B 就可以开始。典型场景是“设计评审”和“文档编写”评审会一开始文档就可以基于初稿动笔不需要等评审完全结束。FF完成到完成A 完成了B 才算完成。典型场景是“测试”和“用户文档”所有用例跑完文档才算完稿但文档可以提前开始写只要在测试结束时同步完成就行。SF开始到完成A 一旦开始B 就必须在此之前完成。这个关系平时用不到但在倒排计划里很有用。比如某一天系统必须上线那么“上线窗口启动”这个活动一开始“停机维护”就必须在那一刻完成。SF 表达的就是这种强制性约束。选逻辑关系时最常见的误区是把所有依赖一律写成 FS。这么做不是不能用但会丢掉并行空间计划会比实际更保守工期偏长。我的做法是先默认 FS把整张图画完然后回头看哪些活动其实可以并行把一部分改成 SS 或 FF。比如两个团队分别做前后端后端接口联调其实在前端开发完成前就可以开始用 SS 滞后比用 FS 更贴实际。改完再算关键路径往往能挤出几天到两周的余量。滞后Lag和提前Lead也要在这个环节定下来。滞后量和逻辑关系配合使用FS 2 表示 A 完成后要等 2 天 B 才能开始比如混凝土浇筑完要养护 2 天。负滞后在项目管理软件里一般叫 Lead表示可以提前开始或重叠。漏掉滞后量会让总工期被算短漏掉提前量会让并行关系不完整两种偏差都会让计划和执行对不上。下面把四种关系列成一张速查表参数设置时直接对照。关系含义典型场景常用滞后写法FS前序完成后续开始模板完成→浇筑混凝土FS7养护等待SS前序开始后续开始设计评审→文档编写SS1评审首日即可动笔FF前序完成后续完成测试完成→文档完成FF0同日收尾SF前序开始后续完成上线启动→停机维护极少用明确依赖时再写2.3 给活动排工期三点估算与 PERT 公式的正确用法逻辑关系定了接下来是每个活动到底要花多少天。很多人直接给一个“估摸数”这在需求明确、历史数据充足的重复性项目里问题不大但在新项目、研发项目里单点估算往往不够用。通用做法是三点估算。每个活动要给出三个输入乐观工期 a、最可能工期 m、悲观工期 b。a 是理想情况下最短工期m 是你真实有把握的值b 是已知风险都爆发时的最差工期。期望工期的计算式是期望工期 (a 4m b) / 6这个公式不是数学考试题它的含义是把最可能值放大到 4 倍权重让结果不会被极端的乐观或悲观值带跑。标准差的计算式是工期标准差 (b - a) / 6标准差的意义在于它能给每个活动一个波动范围。多个活动串成一条路径后各自方差之和就是整条路径的方差再开方得到路径标准差。如果某条路径关键性居中可以用它估算项目在指定日期前完工的概率。这一点在只给一个确定工期的排程里完全做不到而 PERT 天然支持。做蒙特卡洛模拟或者风险量化时三点估算表是最省力的输入。操作上我一般按以下五步来收集和录入这些估算值让责任人对每个活动给出 a、m、b 三个值不许只给一个数将三个值分别填入估算表用公式算期望工期和标准差把期望工期作为网络图的活动工期进入后续时间参数计算如果某个活动标准差过大说明不确定性高标记为风险活动在评审时单独讨论不要对三点估算结果再做“四舍五入”保留一位小数即可避免后续计算误差累积。这里要强调一个容易踩的坑千万不要把三点估算做成 (ab)/2。我见过有人为了减少工作量只估了 a 和 b然后取平均值m 被丢弃。这不是三点估算结果等于认为乐观和悲观概率对半开期望值会被明显拉偏。还有团队把 a、m、b 三个数填成同一个值——那还不如直接单点估算至少不会多一道计算工序。三点估算的核心价值是保留不确定性信息去掉 m 或者抹平三个值它就和普通拍脑袋没有区别。另外工期单位要统一要么全部用工作日要么全部用日历天。混用工作日和日历天是新手最常犯的错养护、审批这类时间如果按日历天算而任务是按工作日排的出来的网络图会出现莫名其妙的偏差。3. 单代号还是双代号网络图画法与转换实践3.1 单代号网络图节点是活动画法最省事单代号网络图AON里每个活动用一个节点矩形或圆圈表示带箭头的线表示逻辑关系。这是现在项目管理软件的默认形态主流项目管理软件里的网络图视图多数是单代号风格。它的优点是画起来直观活动之间的 FS、SS、FF、SF 关系直接写在箭线上不需要额外创造元素缺点是活动信息只能靠节点内文字表达节点多了图会很大。画单代号网络图时我习惯在节点里放三行上面是活动名称中间是工期下面预留 ES / EF 和 LS / LF 的书写空间。这样正推逆推时可以边算边填不用另外拿一张表对着找。如果你只是做快速分析不追求正式文档Excel 里画方框加箭头也完全够用。不过要提醒一点如果活动超过 30 个纯手工绘图很容易漏线或者连错建议先用工序表把依赖关系列清楚再画图。来看一个最小可用的例子。某项目拆出 5 个活动工序表如下活动工期(天)前置活动A5无B3AC8BD4BE2C、D用单代号画图顺序是 A → B然后 B 分叉到 C 和 D最后 C、D 汇到 E。这张图上没有任何额外元素所有信息就是五个节点和四条箭线。这是个标准的“分叉-汇合”结构在真实项目里很常见比如 B 是一个设计阶段C 和 D 分别是两个专业方向的设计输出最后 E 是综合评审。3.2 双代号网络图引入虚工作用来表达并行约束双代号网络图AOA比单代号复杂一个量级。它用箭线代表活动用圆圈节点代表事件或里程碑。换句话说一条箭线就是一个活动它从起始事件的节点出发结束于完成事件。因为活动都在箭线上节点上的编号就成了活动最早最晚时间的锚点所以双代号图在早期工程管理中很流行尤其是建筑工程领域。双代号的核心难点是虚工作。当一个逻辑关系不消耗时间和资源但又必须表达时就用虚箭线来表示也叫虚工作。我总结三个必须使用虚工作的场景一是两个活动有部分共同前置时。比如活动 C 的前置是 A活动 D 的前置是 A 和 B如果不引入虚工作从 B 到 D 的逻辑就无法单独表达因为 C、D 会变成并列。二是在双代号图中两个活动不能共享完全相同的一对起止节点。因为箭头代表活动如果 C 和 D 都是“从节点 3 到节点 4”图上就无法区分它们。解决办法是给其中一个活动加一个虚工作人为拆出一对不同的节点。三是表达“活动完成后部分后续工作可以开始”这种偏 SF 或 FF 的约束时虚工作能给约束提供独立的路径。虚工作常见错误是把它当作真实活动来安排工期和资源。它没有工期没有资源消耗只有一个作用就是让逻辑关系在双代号图里成立。如果某个逻辑已经在真实活动箭线上表达过了再加一条虚工作就是多余连接会让计算出现假的关键路径。我自己的习惯是先用单代号把逻辑图画顺再转成双代号虚工作的位置会清楚很多。3.3 从工序表到双代号网络图虚工作标注三步走把前面的 5 活动工序表转成双代号网络图具体做法可以拆成三步。第一步先画单代号草图理顺逻辑。A 是源活动B 紧随 AC、D 都依赖 BE 依赖 C 和 D。这个步骤不直接产生双代号结果但它能帮你确认逻辑关系没有遗漏。第二步给活动分配唯一的箭线编号。网络图约定节点编号从左到右递增箭线必须从编号小的节点指向编号大的节点。A 可以是 1→2B 是 2→3。到这里都还简单。第三步处理 C、D、E 的依赖。C 和 D 都从前置 B 节点出发但 C、D 是不同的活动不能用同一条箭线。常见做法是在节点 3 之后加一个虚节点把 C 和 D 拆成 3→4 和 3→5 两条箭线然后 C 从 4→7D 从 5→7E 是 7→8。这里注意节点 4 和节点 5 之间要不要虚工作取决于实际约束。我们的例子里 C 不依赖 DD 也不依赖 C所以不需要如果 D 必须在 C 开始之后才能开始就要加一条 4→5 的虚箭线表达这个约束。这一步容易出错的地方在节点编号。有人习惯随手编号画完才发现箭头方向出现编号倒退。建议画草稿时先用铅笔标号检查所有箭线都是从小号指向大号、没有回路之后再正式誊清。回路在双代号图中是致命的它代表逻辑循环计算无法收敛具体会在第 5 章排查部分详细写。3.4 节点编号、里程碑与网络图的检查清单双代号图里节点本质上是事件事件可以是“开始”“完成”或“里程碑”。很多项目经理把里程碑当成一个活动放进网络图这是错误的里程碑没有工期它在网络计划里应该表现为节点而不是活动。如果一个里程碑节点被赋了工期还参与了关键路径计算总工期就会被加长而且加长得毫无意义。画完网络图之后我会按下面这张清单逐项检查避免带着逻辑错误进入计算每个活动有且只有一条对应的箭线所有节点编号递增不存在指向小号的连线网络中不存在循环回路从起点沿箭头方向一定能走到终点每个活动的前置逻辑在图中都能找到对应路径不依赖“常识”补位双代号图中的虚工作只服务于逻辑约束不携带工期和资源里程碑不单独作为活动计时只作为节点存在。这张检查清单不花多少时间但它能挡住大部分低级错误。网络计划工程师的第一步不是计算而是把图画对。画图的时间花得越多后面计算和纠错的时间越少。我用过很多次这样的清单几乎每次都能找出至少一处逻辑漏项或编号问题。在只有十几个活动的项目里这些问题可能还不会造成灾难性后果一旦活动数超过 50带病上路的网络图会让关键路径计算结果完全不可信而那时排查的难度比画图时大得多。4. 六个时间参数与关键路径正推逆推的手算与检查4.1 正推法最早开始时间和最早完成时间的计算有了网络图和活动工期就可以计算六个时间参数这是网络计划技术的核心算法。我先讲正推。正推从网络起点开始向终点方向推进。每个活动有两个值最早开始时间 ES最早完成时间 EF。规则如下起点活动的 ES 0也可以设为项目起始日期但先用 0 方便手算EF ES 活动工期如果一个活动有多个前置活动它的 ES max(所有前置活动的 EF)。取最大值是正推法最容易出错的地方。为什么取最大因为一个活动必须等它所有的前置都完成才能开始前置里最晚完成的那个决定了最早开始时间。比如 C 和 D 都完成后 E 才能开始C 的 EF 是 16D 的 EF 是 14那么 E 的 ES 必须取 16不能取 14否则 E 开始时 D 还没完成。这个规则在所有软件里都是硬约束手工计算时尤其要盯住。用第 3 章的工序表做一个完整手算演示活动工期前置ESEFA5无05B3A58C8B816D4B812E2C、D1618正推结束后项目总工期就是所有终点活动 EF 的最大值。本例里只有一个终点 EEF 为 18项目总工期就是 18 天。如果网络有多个终点比如两个并行分支各自收尾项目总工期必须取 max(所有终点 EF)这个值在逆推法里代表 LF 的起始基准取错的话后面的最迟时间全盘错掉。4.2 逆推法最迟开始和最迟完成的边界条件逆推与正推方向相反从终点向起点推进计算最迟完成时间 LF 和最迟开始时间 LS。规则如下每个终点活动的 LF 项目总工期LS LF - 活动工期如果一个活动有多个后续活动它的 LF min(所有后续活动的 LS)。取最小值的原因和正推取最大值对称一个活动如果太晚完成它最紧迫的那个后续活动就会受影响。必须让这个活动完成得足够早保证所有后续活动都能不晚于它们的最迟开始时间开工。沿用上面的例子项目总工期 18 天活动工期后继LFLSE2无1816C8E168D4E1612B3C、D85A5B50注意看 B 的逆推B 的后继是 C 和 DC 的 LS 为 8D 的 LS 为 12B 的 LF 取 min(8, 12) 8也就是 C 的 LS。这很合理如果 B 等到 12 天才完成C 就没有任何浮动空间了而 C 恰恰是更紧的任务。取最小值在这里不是可选项是硬性规则。正推和逆推完成后每个活动都有四个时间点ES、EF、LS、LF。这四个值就是网络计划里所有时差计算的基础。手算时建议把表排成一行一行边算边填算完一个活动划掉一个避免遗漏。如果有活动在逆推时算出 LS 为负数说明总工期定得不合理需要回到上游检查工期或逻辑关系。4.3 总时差与自由时差两个容易混淆的关键指标时间参数里和实际管理最相关的两个值是总时差TF和自由时差FF它们回答的问题完全不同。总时差 TF LS - ES LF - EF表示在不影响项目总工期的前提下该活动最多可以延误多久。自由时差 FF min(所有后续活动的 ES) - EF表示在不影响任何后续活动最早开始时间的前提下该活动可以延误多久。两者关系很微妙。总时差是全局概念自由时差是局部概念。一个活动可能有 5 天总时差但如果它的后续活动很紧它可能只有 1 天自由时差。换句话讲活动延误 2 天总工期没受影响但后续活动的最早开始时间已经被推迟了这种状态就是“总时差够用、自由时差不够”。实际项目中如果某个关键活动延误后还能保住总时差项目经理容易放松警惕但自由时差已经耗尽下游团队的实际进度会整体后移。所以我习惯把两个值都算出来而不是只看总时差。继续用第 3 章的例子活动工期ESEFLSLFTFFFA5050500B3585800C881681600D4812121644E21618161800D 的总时差和自由时差都是 4 天。它的意思是D 晚开始 4 天不会影响总工期也不会影响 E 的最早开始时间。但如果 D 晚开始 5 天E 的 ES 就要从第 16 天变成第 17 天总工期也可能从 18 天变成 19 天。还有一种情况值得注意活动有总时差但没有自由时差。比如某个活动 A 的总时差 3 天但它的后续活动 B 在关键路径上A 的 FF 为 0。这意味着 A 一旦延误 1 天B 和后续关键路径都会一起延后总工期直接受影响。这时候只盯 TF 会漏掉风险必须看 FF。4.4 关键路径判定总时差为 0 的活动链就是答案计算关键路径最直接的方法是找出总时差为 0 的活动把它们从起点到终点连起来。上面例子里 A、B、C、E 的 TF 都是 0它们组成 A→B→C→E 一条链这就是关键路径。关键路径上所有活动的工期加起来正好等于项目总工期5 3 8 2 18 天。这里有几个容易翻车的细节。第一条关键路径未必只有一条。如果两条并行路径工期相同它们就都是关键路径。比如某项目两个分支各 10 天项目总工期 10 天两条分支上的活动 TF 都可能是 0。这时候如果只盯其中一条另一条上的延误同样会让项目延期。第二条关键路径会转移。当你压缩了某条关键路径上的活动工期原来非关键路径的某条链可能变成新的关键路径。常见于赶工场景缩短 C 之后D 路径变成新的关键路径。所以每次调整工期或逻辑关系后都要重新计算全部时间参数不能只盯着上一次的关键路径。第三条总时差为 0 是概念上的理论判定。实际项目软件里经常出现总时差为负或很小的活动因为计划中的日期已经滞后于目标日期。负总时差表示项目整体已经落后于期望完工日期这时候要压缩关键路径工期或者调整目标日期而不是去和软件“讲道理”。看到负总时差时先区分是计划问题还是进度落后问题再决定下一步。4.5 用一次完整计算验证你的网络图是否正确手算一遍六个时间参数后可以用下面的规则自我验证防止计算过程埋雷所有活动的 ES 必须小于等于 LSEF 必须小于等于 LF等价于 TF 不小于 0总工期 终点活动的 max(EF) 起点活动的 min(LS) 关键路径长度多条关键路径时也同样成立关键路径上每个活动的 FF 和 TF 都必须是 0非关键路径上的活动其自由时差不能大于总时差否则说明正推或逆推至少一处取错任意活动后续活动的 ES 必须大于等于该活动的 EF这与逻辑关系严格一致。如果这五项全部通过网络图和计算基本可信。如果不通过先回头查正推的 max 取法和逆推的 min 取法。手工算错最常见的地方就在这里汇点取小、分叉取大。把这条记住了手算和软件校核都能省出大量时间。5. 网络计划常见问题排查五类翻车现场与修正方法5.1 隐式依赖没写进网络图工期被算短一大截现象网络计划算出总工期 18 天实际执行却要 25 天。项目复盘时发现网络计划里的活动都按图纸要求串好了但同一台关键设备要供两个活动使用这两个活动在逻辑上没有先后关系于是计划里被排成了并行实际上只能串行。原因工序表只写了活动之间的显式逻辑依赖没有把资源共享、场地限制、审批窗口这类隐式约束转成逻辑关系。网络计划技术默认资源无限这个假设在计算阶段是没问题的但排计划时不能把资源冲突抛在一边。解决在建立网络图之前把“是否有共享资源、是否有独占场地、是否有外部审批窗口”逐一问一遍。存在资源冲突的活动要么在逻辑关系上补一条依赖比如“设备 A 未完成前设备 B 不能开始”要么在网络图之外加资源约束检查用资源直方图识别冲突区间。补依赖的方式最简单也最容易让排程软件正确计算我一般优先补依赖实在补不了再用资源平衡。5.2 循环回路哽住了计算关键路径死在原地现象排程软件报错或者自己写脚本正推时死循环日志里能看到某些活动一直处于“前置未完成”状态。原因网络图里存在循环依赖。最典型的是 A 的前置是 B、B 的前置里又有 A或者经过多级传递后绕了回来。常见于多个团队各自维护一段工序表最后合并时逻辑出现环也可能是把“信息反馈”误当成逻辑依赖导致两个活动互相等待。解决画完网络图后先做一次环路检查。手工检查的办法是从起点节点沿箭头方向走如果某个节点被第二次经过就是回路。代码方案更省事在计算脚本里做一次拓扑排序排不出来的活动就是环路节点。把环路中的依赖找出来问一个问题“到底谁必须先完成”去掉多余的反向依赖。对于反馈类信息建议单独用文档管理不要强行塞进网络图。5.3 三点估算变成算术平均PERT 失去了概率骨架现象估算表里 a、m、b 三个值差别很小算出来的期望工期和单点估算几乎一样更有甚者三列填同一个数形式上是三点估算实质还是拍脑袋。原因团队没有历史数据责任人也给不出三种场景的量级于是大家都不愿意“猜”干脆填一样交差。三点估算的公式 (a4mb)/6 本身没有错错在输入数据失去区分度。解决给责任人强制设定取值规则。比如 a 对应“历史最好水平”m 对应“正常水平但资源按承诺到位”b 对应“已知风险全部发生且至少返工一次”。让每个值有不重叠的依据而不是自由发挥。a 和 b 的跨度不够时说明责任人没有认真推演风险这时候要带着风险清单重新过一遍而不是接受那个看起来整齐的数字。另一个办法是把历史项目的工期数据按分位数切开P25 当 aP50 当 mP90 当 b。没有历史数据的团队可以先从高相似度项目的日志里抽数比让责任人凭空填要可靠得多。5.4 只算工期不算资源计划成了纸面蓝图现象网络计划显示 18 天完工开工后第五天就发现班组人力不够部分活动被迫停工等待实际工期推到 23 天。关键路径上明明有浮动却仍然延期。原因CPM 的假定是资源充足、可以按逻辑关系随时开工。现实是同一个团队同时在多个活动上工作或者一个人的任务被排得比可用时间还多。网络计划给出了“逻辑可行”的最快路径但没回答“资源可行”。解决在关键路径计算完成后叠加资源日历检查。把每个活动的资源需求量和可用资源量按月或按周汇总画出资源直方图哪里超出可用量哪里就是资源冲突。解决冲突有几种常见做法推后非关键活动、延长关键活动工期、调整逻辑关系把并行改成部分串行。这些动作做完之后需要重新计算一次时间参数因为任何一次调整都可能改变关键路径。这一轮检查虽然麻烦但它是网络计划从“理论可行”走向“可执行”的必经步骤。5.5 活动编号混乱双代号图逻辑对不齐现象双代号网络图节点编号跳来跳去有的箭线从编号大的节点指向编号小的节点算时间参数时结果异常重新检查才发现多条箭线的逻辑画错了。原因画图时没有按从起点到终点的顺序递增编号中途又插入新活动导致编号和实际顺序脱节。特别是虚工作引入后编号更容易乱连带着状态事件的前后关系也错位。解决双代号图坚持“从左到右、编号递增、入度优先”三个原则。每添加一个活动先确定它的所有前置节点都已存在再分配新节点编号。如果在过程中要插入活动不要用原编号改直接给新节点一个更大的编号保证图面从左到右的顺序不被破坏。画完之后做一次“节点编号单调检查”所有箭线的起点编号必须小于终点编号一条违反就会导致整个逆推结果不可信。这个检查和代码里的拓扑序列检查是同一件事手工做的时候把它当成例行步骤不要只靠眼睛“看个大概”。6. 让网络计划自动跑起来Python 脚本与结果自查6.1 用 Python 表达网络十分钟算出关键路径活动超过 30 个时手算效率太低也容易因为取错 max/min 值出错。我通常用一段固定结构的脚本来做计算下面这段代码可以直接复制进 Python 跑通然后把活动数据替换成你自己的工序表即可。# 活动表活动名 - 工期 前置活动列表 network { A: {dur: 5, pred: []}, B: {dur: 3, pred: [A]}, C: {dur: 8, pred: [B]}, D: {dur: 4, pred: [B]}, E: {dur: 2, pred: [C, D]}, } # 1. 先建立每个活动的后继列表逆推时会用到 succ {name: [] for name in network} for name, attr in network.items(): for p in attr[pred]: succ[p].append(name) # 2. 正推ES max(所有前置的 EF)EF ES dur es, ef {}, {} todo set(network.keys()) while todo: for name in list(todo): if all(p in ef for p in network[name][pred]): es[name] max([ef[p] for p in network[name][pred]], default0) ef[name] es[name] network[name][dur] todo.remove(name) # 3. 项目总工期 所有终点活动 EF 的最大值 ends [n for n in network if not succ[n]] project_end max(ef[n] for n in ends) # 4. 逆推LF min(所有后继的 LS)LS LF - dur ls, lf {}, {} todo set(network.keys()) while todo: for name in list(todo): if all(s in lf for s in succ[name]): lf[name] min([ls[s] for s in succ[name]], defaultproject_end) ls[name] lf[name] - network[name][dur] todo.remove(name) # 5. 总时差 TF 和自由时差 FF tf {n: ls[n] - es[n] for n in network} ff {} for name in network: if succ[name]: ff[name] min(es[s] for s in succ[name]) - ef[name] else: ff[name] project_end - ef[name] for name in network: print(f{name}: ES{es[name]:2}, EF{ef[name]:2}, fLS{ls[name]:2}, LF{lf[name]:2}, TF{tf[name]:2}, FF{ff[name]:2}) print(项目总工期:, project_end) print(关键路径:, [n for n in network if tf[n] 0])代码逻辑分五步先算后继关系再正推再定总工期再逆推最后算时差。正推循环用all(p in ef for p in ...)判断前置是否都已经算完default0处理没有前置的起点活动。逆推循环的all(s in lf for s in succ[name])判断后继是否都已经算完defaultproject_end处理没有后继的终点活动。这个结构的好处是不需要手动维护拓扑顺序只要网络本身无环两三轮循环就收敛了。跑一遍得到的结果里关键路径是 A、B、C、E项目总工期 18 天D 的 TF 和 FF 都是 4和前面手算完全一致可以用作脚本的基准测试。使用时要确认所有活动名唯一前置列表里不能出现活动表中不存在的名字否则ef[p]会直接 KeyError。出现这个报错不要慌回到工序表核对活动名拼写这是最常见的错误来源。6.2 结果验证的三个自查点不管用手算、Excel 还是脚本算完都要做三件事验证第一检查关键路径上的活动 TF 是否全为 0手工数一下关键链长度和项目总工期是否相等第二随机挑一个非关键路径活动手工重算它的 EF 和 LS看看脚本给出的结果能不能对上第三把其中一个关键活动工期增加 1 天重新跑一遍确认项目总工期也跟着增加 1 天。如果第三点成立说明关键路径识别正确如果不成立说明网络里还有另一条更长的路径你没发现。我做完网络计划后习惯保留一张最终版的工序表表里同时记录每个活动的 ES/LS/TF/FF 和它对应的责任人字段。这张表比网络图更好传播评审会上大家看得更快。需要提醒的是随着项目推进实际状态会不断变化网络计划不是做一次就完事每条实际延误都要回填到表中重新计算。我的原则是每周至少重新跑一遍脚本发现关键路径转移就立刻同步给所有相关方。把计算自动化之后这只是一次双击的事没有任何理由拖着不更新。希望这些做法能帮你在下一次排计划时把网络计划技术真正用起来而不是只停留在图面上。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑