简介:面向制造业计划与调度岗位的APS高级排产系统资料包,覆盖需求预测、产能规划、多级物料需求计划、约束优化、实时调度与库存管理等模块,能帮助读者理解生产排程的核心逻辑及ERP/SCM/MES系统集成方法。包内以Java/Class源码、JSP/HTML页面及PNG/JPG图表为主,辅以CSV数据、Jar依赖库、数据库备份与配置文件,共707个文件,RAR压缩包仅4.01MB,下载后便于本地部署和分模块查阅。目前已有1141人学习,适合具备一定编程基础、希望深入APS系统开发或选型的工程师和学生。资料中既包含可运行的工程源码与页面素材,也提供LP优化模型、数据库备份和工程备份文件,可支撑源码研读、二次开发与教学演示,是企业推进智能排产时具有较高参考价值的资源。
1. APS高级排产系统:先算产能再排工序,治的不是排程而是交付焦虑
APS高级排产系统这几年被制造企业反复提起,但很多车间上完MES、ERP接入APS后,计划员还是抱着Excel不放。原因很简单:APS排出来的甘特图看起来很漂亮,却和现场“能不能干完”脱节。APS的本质不是替代计划员的经验,而是把“有限产能、工序依赖、物料齐套、交期约束”四个变量放进同一个模型里,用算法算出一个可执行的时间表。它真正解决的是“插单一来全盘重排”“设备利用率只有40%”这类慢性问题,适合小批量多品种、瓶颈工序明显、交期压力大的离散制造场景。它不便宜也不轻,但方向对了,比单纯换一个更贵的ERP值钱。
2. 排产原理与选型:先从约束聊起,再谈正排倒排与方案取舍
2.1 无限产能与有限产能之差:MRP为什么老是给你“画饼”
很多制造企业第一次接触APS,都是因为MRP展开出来的计划根本无法执行。MRP跑出来的“建议开工日期”建立在无限产能假设上——它假设所有设备随叫随到,工人随时有料。实际车间里,一台加工中心既是瓶颈又是共享资源,三个订单同时要使用这台设备,就必须排队。这就是APS要处理的有限产能排产问题。
用大白话说:ERP里的计划是在“有无限多台设备”的平行世界里排的,APS是在“今天下午只有这台机器有空”的现实世界里排的。从数学模型看,有限产能排产问题需要同时决策三件事:每道工序在哪个设备做、什么时间开始、什么时间结束。加上物料齐套、工序先后、设备独占这些强约束,问题复杂度瞬间变成NP-hard级别的组合优化,这也是为什么不能用Excel硬算、必须依赖求解器或启发式算法的原因。
我一般会把排产模型抽象成三个要素来看:决策变量、目标函数、约束集合。决策变量是每道工序的开始时间和设备指派;目标函数通常写成交期相关指标,比如加权拖期最小化;约束集合包含设备唯一性约束、工艺顺序约束、物料供应约束和班次日历约束。把这三件事写清楚,整个排产引擎的骨架就立住了。
2.2 正排、倒排与插单重排:三种策略覆盖九成场景
选排产策略是APS参数配置里最先要决定的事。常见的有三种:正排、倒排、插单重排。
正排是从当前时间点出发,把订单尽可能早地排下去,碰到设备冲突就顺延;这种策略优先保证设备利用率,适合车间产能紧张、交期经常延后的场景。倒排是从订单交期出发,沿着工艺路线反向推算每道工序最晚完工时间,再倒推开工时间;它优先保交期,适合产能有余量、但对客户承诺很在意的场景。
如果两种都做过,很快会发现一个现实:单纯正排会让所有订单都延期,单纯倒排会让废料堆满车间,因为倒排算出来的开工时间往往比物料到位时间还早。我的习惯是默认用正排,同时引入“交期紧迫度”权重,让急单在排序时抢到前面的产能窗口。
插单重排则是另一类高频场景,也是计划员最头疼的场景。客户插单不是要你把所有订单全部重算一遍,而是要让新增订单挤出产能。这里有个关键参数:全局重排范围。我一般会把“已下发到MES且已开工的工序锁死”,只允许新订单抢占未开工订单和空闲产能。否则插单一来全厂计划全部漂移,车间老师傅直接不看了。下表是我常用的策略选择参考。
| 场景 | 首选策略 | 关键参数 | 风险点 |
|---|---|---|---|
| 产能紧张、订单经常延误 | 正排为主 | 排序权重按交期紧迫度 | 紧急订单可能超期 |
| 产能有富余、重承诺交付 | 倒排为主 | 安全提前期、缓冲时间 | 中间库存增加 |
| 频繁插单 | 正排+锁定已开工工序 | 锁定窗口、重排深度 | 局部优先级失真 |
2.3 自研、开源组件还是商业套件:三种路线的实施差异
选型是很多团队容易踩坑的地方,原因在于APS这类系统的价值不在代码量,而在模型、算法和主数据质量。低估实施成本的人,多半会在“换型时间怎么进约束”“插单后哪些工序能动”这类细节上反复返工。
自研路线适合企业有算法团队、愿意长期维护排产引擎的场景。常见做法是拿Python封装开源约束求解库(CP-SAT这类),把业务约束写成脚本,运行速度快,调参灵活。缺点是排产模型从零验证,边界情况处理成本高;我见过不少自研到一半的团队,最后卡在“换型时间要不要占设备日历”这种细节上。
开源组件路线胜在免费、可控,但APS不是一个单点软件,开源生态比较零散,多是企业自己拼装数据接入、算法、甘特图展示、权限管理一整套能力,实施周期并不短。商业套件最大的价值是把成熟的建模体系和行业参数沉淀在软件里。某主流ERP厂商自带的排产模块适合本来就在用其ERP的企业,胜在集成成本低,缺点是模型黑匣子程度高。国外专门做APS的厂商算法成熟,但要接受数据接口要单独定制、实施价格不低的现实。
选型要提前给硬指标:排产引擎每天要跑几轮全量重排、单次计算时间上限是多少、计划员是否需要在甘特图上做交互式调整。这三条直接决定你买回来的系统是工具还是摆设。全量重排超过十分钟,计划员绝对等不了,他会选择回到Excel。
3. 主数据与数据集成:BOM、工艺路线和资源日历的收拾过程
3.1 五大主数据与一次物料清单清洗实操
APS不是装了就能用的系统,它排出来的时间表是否可信,七成取决于主数据是否干净。主数据至少包括五类:物料表、BOM(物料清单)、工艺路线、资源(设备/工装/人员)、日历(班次/节假日)。其中任何一类有脏数据,排产结果都会出现“排了但做不了”的情况。
最典型的是BOM问题。某次模拟项目的数据检查里,BOM单层循环直接让展开死循环,整个排产Batch卡了40分钟。这类脏数据在ERP里不容易暴露,但到了APS的物料齐套校验环节就会被放大。常见做法是先导出一张BOM快照表去做自动清洗,SQL第一步是找出完全重复的BOM关系:
-- 检查BOM表中同一父件、子件、用量、单位重复的脏数据 SELECT parent_sku, child_sku, qty, uom, COUNT(*) AS dup_cnt FROM bom_header GROUP BY parent_sku, child_sku, qty, uom HAVING COUNT(*) > 1 ORDER BY dup_cnt DESC;这段SQL的作用是把“同一父件、子件、用量、单位出现多次”的重复记录捞出来。这些数据在ERP里不会报错,但在APS做多级BOM展开时,会导致物料需求被成倍放大,齐套率永远算不准。参数上要注意,GROUP BY里除了parent_sku和child_sku,必须把qty和uom也带上,因为不同用量和单位的BOM关系是合法的,不能一律当成重复。
第二步是查BOM的闭合环,用递归查询把父件展开后自身再次出现的记录捞出来:
-- 用递归查询找到BOM闭环,父件展开后自身再次出现即为环 WITH RECURSIVE bom_chain(parent_sku, child_sku, depth) AS ( SELECT parent_sku, child_sku, 1 FROM bom_detail UNION ALL SELECT b.parent_sku, c.child_sku, c.depth + 1 FROM bom_detail b JOIN bom_chain c ON b.child_sku = c.parent_sku WHERE c.depth < 20 ) SELECT DISTINCT parent_sku FROM bom_chain WHERE parent_sku = child_sku;递归深度我限制在20层,因为超过20层的BOM在实际制造里基本不存在,出现多半是闭环或者数据建错。找到环后再回到ERP里手工修正,改正后重新展开一次。这类清洗动作最好固化成一个批处理脚本,每次从ERP同步完数据都自动跑一遍,否则排产系统跑得再快,也只是在脏数据上面快速做出一个错误计划。
3.2 资源建模:把“一台设备”变成“一段时间内可用的产能”
设备建模是APS里最容易被低估的部分。企业给APS导入设备清单时,往往只导了设备编号和名称,而排产引擎需要的是一个“带有时间属性的产能池”。
资源模型的常见做法是把设备拆三层看:设备组、单台设备、日历。设备组是具备同样加工能力的一组设备,排产时可以让订单在组内任意分配;单台设备才是真正排产的对象,每台设备有自己的班次、效率和可用时间段;设备日历负责描述哪台设备在哪个时间段能用、能用的产能是多少。
下面这个JSON示例展示一个典型的设备资源结构:
{ "resource_id": "MC-010", "resource_name": "立式加工中心1号机", "group_id": "GRP_MACHINING", "unit": "hour", "calendar": { "work_shift": [ {"day": 1, "start": "08:00", "end": "20:00"}, {"day": 2, "start": "08:00", "end": "20:00"}, {"day": 3, "start": "08:00", "end": "20:00"}, {"day": 4, "start": "08:00", "end": "20:00"}, {"day": 5, "start": "08:00", "end": "20:00"} ], "effective_start": "2026-01-01", "effective_end": "2026-06-30", "efficiency": 0.85 }, "constraints": { "setup_time_minutes": 30, "max_parallel_jobs": 1 } }这个JSON是排产系统读取资源的典型结构。关键字段有三处:calendar里的班次时间段,决定了设备什么时候可用;efficiency字段是设备效率因子,实际可用产能等于班次时长乘以效率,因为设备不可能百分之百产出;setup_time_minutes是换型时间,指设备从上一个订单切换到下一个订单时的准备时间,这是排产中最容易“水土不服”的参数。
换型时间设成0,排产结果会非常乐观,实际上现场停工等换型的时间一大把;设得过高,产能又被白白浪费。我的经验是先用过去一个月的实际换型平均值试跑,输出结果给车间主任看一轮再调整,不要第一次就追求精确。
3.3 数据集成:中间库同步的核心逻辑与常见坑
很多APS项目死不在算法上,死在数据同步上。APS要用的数据在ERP里,排完产要把结果写给MES,中间还要和实时库存、设备状态打交道。数据集成常见做法是中间库模式:ERP把主数据和订单写入中间库,APS读取并组织成自有数据模型。
同步分两类:主数据同步和动态数据同步。主数据(物料、BOM、工艺路线、资源)更新频率低,用每日增量即可;订单、库存这类动态数据,需要每几分钟同步一次,否则排产用的物料余量是半小时前的,很容易欠料。
下面是一个定时同步任务的核心逻辑,用Python表示:
import time import requests import pandas as pd def sync_master_data(erp_api, target_db, sync_type="daily"): # 从ERP接口获取增量数据,更新时间从last_sync开始 last_sync = load_last_run_time() payload = {"updated_from": last_sync, "sync_type": sync_type} # 常见做法:分物料、BOM、工艺路线三张表依次拉取 response = requests.get(erp_api, params=payload, timeout=300) if response.status_code != 200: log_error("ERP接口返回非200,保留上次同步状态") return False # 拉取的数据先过一轮数据清洗再写中间库 df = pd.DataFrame(response.json()) df = clean_bom(df) # 清洗BOM闭环与重复行 df = validate_sku(df) # 物料主数据有效性检查 target_db.replace_table("t_bom_snapshot", df) update_last_run_time(time.time()) return True if __name__ == "__main__": # 常见做法:每30分钟同步一次主数据,每5分钟同步一次库存 while True: sync_master_data("erp/api/v1/bom", db, "daily") time.sleep(1800)这个脚本展示的是一条最朴素的数据同步链路。两个地方值得注意:第一是last_run_time记录机制,同步一定要带增量时间戳,否则每天全量重推数据,既慢又把ERP的接口压垮;第二是小表用replace_table全表替换可以,大表一定要用增量更新。项目里遇到“BOM变了但APS不更新”八成是时间戳失效,或者只有表头更新没触发子行更新,需要在ERP端埋触发点。
中间库还会遇到单位不一致的问题。比如ERP里采购单位是“件”,生产单位是“箱”,一箱24件,APS如果直接读采购单位,齐套数量就会差24倍。这类单位映射表要在集成层处理好,不要到排产引擎里再临时换算,临时换算的逻辑没人维护,迟早翻车。
4. 建模与参数配置:从白纸到一张下发MES的合格甘特图
4.1 目标函数:优先级的本质是让所有订单的加权拖期总和最小
排产引擎拿到数据和约束后,按什么标准来算?这就是目标函数。绝大多数APS项目的业务目标可以收敛成一个指标:加权拖期最小化。简单说,每个订单有一个交期,系统希望在满足约束的前提下,让所有订单的拖期天数总和最小;无法用同一指标量化的场景,就考虑设备利用率最大化或换型次数最小化。
订单优先级本质就是权重。A客户订单权重1.2,普通客户权重0.8,交期只剩两天的订单权重加乘系数1.5,紧急程度不同,在目标函数里的分量就不同。用Python表达目标函数很直观:
# 目标函数:最小化所有订单的加权拖期之和 def objective(schedule, orders): total_weighted_tardiness = 0 for order in orders: completion = schedule.get_completion_time(order.id) due_date = order.due_date tardiness = max(0, completion - due_date) # 负数视为不拖期 total_weighted_tardiness += order.weight * tardiness return total_weighted_tardiness # 某订单交期为第5天结束,权重1.2,完工时间第6天,拖期1天贡献目标值1.2这个目标函数的逻辑很简单:完工时间减去交期,只有正数才算拖期,拖一天贡献权重乘一。权重设得越大,这个订单在算法迭代时被优先照顾的程度越高。但这里有个容易忽略的参数:tardiness的单位,生产环境里按工作日算,不要按自然日算,否则周末两天也会被算成拖期,订单排名顺序会失真。
4.2 参数配置:影响排产结果的六个关键旋钮
APS部署完成后,真正影响计划员信任度的,往往不是算法本身,而是参数怎么调。下面六个参数是每次上线都要跟计划员一起过一遍的:
| 参数 | 推荐初始值 | 影响 | 调参注意点 |
|---|---|---|---|
| 排产区间(horizon) | 14天 | 越长全局越优,计算越慢 | 超过30天大概率数据漂移 |
| 排序规则(sequence) | 交期升序 | 决定初始解质量 | 优先用EDD起步 |
| 批次合并 | 关闭 | 影响换型次数与批量大小 | 单件流开启,批量场景关闭 |
| 并行工序拆分 | 关闭 | 同一订单多工序并行会压缩周期 | 离散制造慎开,流程工业可开 |
| 是否允许中断 | 否 | 允许工件跨班次等待或转机 | 频繁插单时开启,但要配合锁定策略 |
| 锁定策略 | 锁定已下发工序 | 防止全局重排打乱执行 | 所有参数里最影响计划稳定性 |
这些参数不是独立的。比如开启批次合并之后,换型次数会下降,但单个订单的完成时间会后移;开启并行工序拆分之后,订单周期缩短,但设备资源被订单内部工序互相抢占的概率变大。常见的调参顺序是:先把交期升序跑一轮,再逐步打开批次合并看换型次数,最后再考虑并行拆分。
配置文件的常见写法是把这些参数独立成JSON片段,方便测试不同参数组合:
{ "horizon_days": 14, "sequence_rule": "EDD", "enable_batch_mixing": false, "enable_parallel_splitting": false, "allow_interruption": false, "locked_scope": "released_operation", "solver_time_limit_seconds": 120 }建议计划团队用三套参数存档:一套保守参数(每天全量重排用)、一套激进参数(每周重排但允许局部扰动用)、一套插单参数(跑局部重排用)。三套参数分别验证,不要一套参数跑到底。
4.3 甘特图交互调整:算法只是起点,计划员的拖拽是终审
算法给出的排产结果只能算是初稿,因为系统永远不知道现场哪些工序“必须连着做”,哪些可以断。这个环节需要一个可操作的甘特图界面。计划员选中一个工序,拖到另一个时间段,系统重新校验约束并给出反馈。用JavaScript表达甘特图拖拽后的回调逻辑:
// 甘特图上某工序被拖拽到新的开始时间 function onOperationDragEnd(operationId, newStartTime) { const op = getOperationById(operationId); const conflict = checkResourceConflict(op.resourceId, newStartTime, op.duration); if (conflict) { toast("该设备在目标时间段已被占用", "warning"); revertOperation(op); return; } // 校验工艺顺序:后工序开始时间不能早于前工序结束时间 const previousOp = getPreviousOperation(op.processRouteId, op.seq); if (previousOp && newStartTime < previousOp.endTime) { toast("前道工序未完工,不能调整到这里", "error"); revertOperation(op); return; } // 校验通过后写入调整记录,并触发局部重排 updateOperationTime(op.id, newStartTime); triggerLocalReschedule(op.orderId); }这里一共有两次校验:第一次是设备资源冲突校验,被拖拽的目标时间窗口里设备不能有重叠任务;第二次是工艺顺序校验,前道工序没完工,后道工序不能开始。项目里遇到过的问题是:计划员把某道工序拖到了周末,设备日历不答应,系统却没有弹提示,结果周一才知道计划被退回来了。所以回调逻辑里一定要把设备日历校验也做进去,否则拖拽体验和实际排产结果对不上。
触发局部重排时要小心:不要对整个订单的所有工序都重排,只让后续工序联动顺延。改动范围越小,计划越容易被现场接受。
4.4 下发MES:工序工单的字段映射与齐套校验
计划排完后,真正让车间动起来的是一张张工序工单。APS下发MES的常见字段包括:订单号、物料编码、工序号、设备编号、计划开始时间、计划结束时间、数量、优先级。下表是字段映射的简化示例:
| APS字段 | MES工序工单字段 | 说明 |
|---|---|---|
| order_no | work_order_no | 关联生产订单 |
| item_code | item_code | 物料编码 |
| process_no | operation_no | 工序序号 |
| resource_id | workcenter_code | 设备编号 |
| plan_start_time | planned_start_time | 计划开始 |
| plan_end_time | planned_end_time | 计划结束 |
| quantity | planned_qty | 计划数量 |
| priority | priority_order | 下发优先级 |
齐套校验收在哪儿做很关键。常见做法是APS算完排产结果后、下发前,对每张工序工单做一次物料齐套检查。如果某工单所需物料在开工时间点还没入库,系统不应直接下发,而应该打回并标记“欠料等待”。否则车间拿到工单也没法开工,APS产出的漂亮计划会死在物料上。欠料标记之后最好回到排产引擎重新排一次,让计划跟着真实物料到位时间走。这一步逻辑上不难,但很多项目在集成时漏配,导致系统只下发不重排,前脚排完计划后脚就在库里缺料,现场开不了工。
5. 排产避坑指南:五个因数据、参数和流程翻车的高频记录
5.1 为什么排产结果看起来“很聪明”,但现场就是不认
APS项目上线前,排产结果在电脑上永远是完美的。但验证排产系统是否可信,不是看甘特图有没有错位,而是看车间实际执行后计划达成率能不能过80%。项目里常见的情况是:计划员拉出甘特图觉得很像那么回事,实际执行两天后偏差大到完全没法看。问题多半不是算法算错了,而是模型里少了现场真实的隐性约束。下面五条都是项目里反复出现的高频踩坑,每条都按现象、原因、解决三部分记录,直接对照排查用。
5.2 高频踩坑记录一:已完成工单被重新排到未来三天之后
- 现象:系统跑完排产,前一天已经完工的工单出现在未来三天的工序序列里,数量还翻倍了。
- 原因:排产引擎在读取工单状态时没做“完成状态过滤”,把已完工工单当成未完工工单重新释放;另一个常见原因是APS的时间轴没以当前系统时间为起点,而是用了上次运行快照的时间。
- 解决:排产启动前加一道强制检查,运行开始前读取当前系统时间作为排产起始时刻;对工单状态字段过滤,只纳入created、in_progress状态的工单,completed状态直接跳过。
5.3 高频踩坑记录二:设备产能统计虚高30%,排产结果偏乐观
- 现象:APS算出来的设备负荷率85%,车间实际产能利用率只有55%,排出来的计划根本执行不下去。
- 原因:资源建模时用了“设备组”作为排产对象,没落到底层具体设备;或者设备日历里填了8小时班次,但实际有效加工时间只有5小时,上下料、换型、休息都被算成产出时间。
- 解决:排产对象必须细化到单台设备,设备日历的有效时间填实际可加工时间,换型时间单独建立约束字段,不能混在加工工时里。负荷率虚高比偏低更可怕,计划员一旦发现系统永远在乐观,就直接弃用了。
5.4 高频踩坑记录三:插单一次,全厂计划全白排
- 现象:客户临时插入一个急单,计划员在系统里点击重新排产,结果所有已下发的工单全部被移动,车间里机器还没来得及做完的活也被改到别处。
- 原因:默认全局重排策略,没有区分“已开工工序”和“计划中工序”。
- 解决:设置锁定策略,已下发到MES、已开工或已完工的工序一律排除在重排范围之外;插单只抢占未开工订单和空闲产能。同时给计划员一个“影响订单清单”,重排后能一眼看出哪些订单被推迟了。
5.5 高频踩坑记录四:BOM同步只更新了表头,齐套率永远是错的
- 现象:ERP里一张BOM换了个物料版本,APS的齐套率却一直显示旧物料欠料,新物料库存也没被识别。
- 原因:增量同步一般按表头更新时间去拉数据,BOM子行被修改但表头时间戳没变,导致APS拿到的还是旧版本。
- 解决:ERP侧做BOM修改时强制同步更新表头时间戳;集成层用当前版本BOM全量快照替换,不在线做子行级合并。对已释放的订单,BOM变更后还要重新触发一次齐套校验,避免漏检。
5.6 高频踩坑记录五:车间主任手动改了计划,APS一跑全被覆盖
- 现象:计划员在APS里改好的甘特图,车间主任也在MES上手工调整了几个工单的开始时间,APS下一次全量重排后全部还原,现场炸锅。
- 原因:MES上的手工调整没有回写APS,系统不知道这些工序已经被改动了。
- 解决:在集成逻辑里加“MES回写”通道,MES上的开始、完工、调整记录定期回写APS并标记为已锁定;APS重排时不占用已锁定设备窗口。说到底,APS不是一次性交付方案,它是人机协作机制,系统的排产结果和现场的调整记录必须双向握手。
6. 进阶验证:用历史数据离线回放100圈,给排产方案做一轮“后悔药”检验
APS投产后不能只看一次排产结果就收工。真正检验排产模型有没有用,跟业务历史对比是最稳妥的方式。常见做法是历史数据回放:取出过去90天的真实订单、BOM、设备日历和实际完工时间,把APS参数设成“只读”,让系统按当时的订单状态重新排一遍,然后与车间实际执行结果对比。
对比的指标我常用三个:计划达成率(实际完工时间在计划完工时间正负一天内的工单占比)、平均拖期天数(全部订单实际完工减去交期的平均值)、设备利用率(按设备有效时间计算的负荷率)。这三个值如果APS回放结果不比历史实际差,模型才算通过了第一步。下面的Python脚本用一张历史工单表就能跑出这三个指标:
import pandas as pd def evaluate_reschedule(actual_df, plan_df): # actual_df: 列名 work_order_no, actual_finish_time, due_date, workcenter # plan_df: 列名 work_order_no, plan_finish_time merged = actual_df.merge(plan_df, on="work_order_no", how="inner") # 不要用自然日作为拖期单位,工作日更符合生产实际 merged["delay_days"] = (merged["actual_finish_time"] - merged["plan_finish_time"]).dt.days merged["is_on_time"] = merged["delay_days"].abs() <= 1 plan_achieve_rate = merged["is_on_time"].mean() avg_delay = merged["delay_days"].mean() # 设备利用率 = 实际占用台时 / 日历有效台时 used_hours = actual_df.groupby("workcenter")["used_hours"].sum() available_hours = get_calendar_available_hours() # 从APS日历表读取 return { "plan_achieve_rate": plan_achieve_rate, "avg_delay_days": avg_delay, "utilization": (used_hours / available_hours).mean() }用work_order_no做关联时要注意,同一个订单号排了多道工序的情况很常见,需要按工序号再做去重,否则计划达成率会被稀释。这个脚本跑出来的三个数,适合放进每周的排产复盘会里跟踪,而不是只在项目验收时看一次。
回到最开头那个问题:APS高级排产系统到底值不值得上?我的答案从没变过——值得,但前提是先把数据洗干净、把策略定清楚、把调度员的经验用参数表达出来。算法负责穷举,人负责决策,系统才会成为真正能用起来的排产工具。从那以后,我每一次给企业做APS方案,都会先跑一轮历史数据离线回放,强制看一遍计划达成率的对比,再决定要不要继续往下谈。希望这个习惯对你也有用,希望帮到你。
本文还有配套的精品资源,点击获取