生产排程的算法.docx
- 文档编号:17483428
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:30
- 大小:21.83KB
生产排程的算法.docx
《生产排程的算法.docx》由会员分享,可在线阅读,更多相关《生产排程的算法.docx(30页珍藏版)》请在冰点文库上搜索。
生产排程的算法
生产计划的生产排程的算法
制造业的ERP系统应该以计划为核心,特别是生产计划如何合理的进行排产显得尤为重要。
但如何实现生产计划为核心?
我想,生产排程系统的实施,是对此问题的最好答复。
所谓"生产排程"通俗讲,是指生产计划和作业计划的统称。
通常企业制定生产计划的过程一般分成两部分,首先是生成主生产计划,其次是根据主生产计划生成生产作业计划。
"主生产计划"一般来源于订单,部分企业来源于市场预测,安排一个生产计划,基本是管理者在进行决策,人的因素起绝对作用。
这个过程中会有一些行业或者企业的特别计算方法,需经过一些四则运算式的统计分析。
但是,光有主生产计划是远远不够的。
一个简单的主生产计划的生产要求,要把它自动分解为复杂、具体的生产作业过程,这就是详细生产排程,是生产排程系统真正核心功能价值的体现。
一般说,生产作业计划越详细,它给出的信息越丰富、越有价值,相应计算起来也就越困难。
生产作业计划越粗略,越接近主生产计划,信息越少、价值就越低。
企业总是希望自动得到尽可能详细的作业计划,减少作业下达的层次。
但是ERP在这方面遇到了真正的技术瓶颈。
就我目前所见,几乎全部的ERP生产管理都是从四则运算的主生产计划入手,重点利用BOM解决MRP物料需求计划,之后再解决生产过程的记录和统计。
如果考虑生产计划全方位信息,减少人为因素影响问题,生产排程系统可以满足你的要求。
生产排程系统是基于ERP系统结构设计而成,生产排程系统可独立于ERP系统,作为ERP系统高级功能的一个模块,帮助企业解决:
一、订单管理跟踪问题
通过需求整理平台实现营销需求订单与生产需求的衔接。
通过排程平台实现计划订单排程、生产作业下达和管理、任务完工到中转出库的全面订单跟踪管理。
二、生产排程问题,实现总装任务排产到生产线的管理
按任意需求时间范围、排程时间范围执行预排处理。
按提前天数、生产需求时间、订单优先级、排程分类、生产线优先级、线能力执行生产线分配。
依据需求时间的固定自动创建固定的计划订单。
按生产线优先级、产能、折返时间等平衡生产线的负荷。
计划订单生产线的换线处理、排程分类变更引发的预排自动换线处理。
三、实现总装部装的按需联动处理
总装部装跟单同步排程。
总装部装跟单任务同步下达。
总装部装计划同步变更调整。
总装部装跟单件按规则同步分配到相关生产车间。
其次,排程平台的实施,推进生产管理模式的变革
计划层次减少,计划集中处理加强。
排程的联动处理,加速了计划与生产的响应效率。
减少传统计划排产的出错机率:
如总装部装同步排程、同步下达,时间差异、数据差异减少。
重新界定主计划员、生产部计划员、车间计划员的职责。
强调车间层面的执行与现场跟进,提高了发现问题解决问题的精准性、时效性。
最后,生产排程系统主要由:
基础数据设置、需求平台、预排程和排程、排程工作台核心四部分内容组成。
基础数据主要是把企业生产人员的想法,通过系统进行固化,通过系统强大的计算功能对计划进行优化和排程。
需求平台:
主要通过需求平台和其他系统或者预测进行连接,获取订单信息和预测信息,同时对加载的这部分需求信息进行整理和维护。
预排程:
按所有生产订单的优先级,按照一定的次序时间安排到具体生产线上;在排程时考虑折返天数;考虑能力约束;考虑排程需求成组;考虑换线时间;考虑已经确认的计划订单和车间任务;考虑排程时间栏,以确定排程计划在该时间范围内计算;考虑不同的订单类型。
排程:
把生产线上计划定单,按照顺排的规则,重新安排计划定单;在排程时仅考虑生产线能力;生成总装计划定单;跟单部件计划定单生成;未确认物料定单的报告;实际排程和需求差异报告;成组需求排程例外报告;能力例外报告。
排程工作台:
排程计划生产订单的下达;对排程中订单优先级的调整;对排程产品生产线的调整;排程订单的重排;车间任务的重排;车间某个计划订单树的重排;车间某个需求订单树的重排;查询每条线上生产任务清单;查询需求订单和实际排产订单的时间安排;查询能力负荷情况提示;查询及跟踪按照某个需求的订单树状态。
算法
一个根据主生产计划进行生产排程的算法,供各位研究产品技术栏目总是空谈的多,现在来点刺激的。
公布一个根据主生产计划进行生产排程的算法,供各位研。
算法体现两个基本原则:
1、需求拉动原则2、物料供需综合平衡原则//--------------------------------------------------
type
NodeRecord1=record
nodetype:
integer;{类型:
0-流程节点1-配方节点2-半成品物料节点3-原始物料节点}
MaterialId:
string;{物料编号}
MaterialName:
string;{物料名称}
MUnit:
string;{计量单位}
stepid:
string;{工序编号}
stepname:
string;{工序名称}
ProRate:
real;{全程投料比例}
Number:
real;{实际作业需求量}
proneed0:
real;{理论投料需求量}
proneed:
real;{实际投料需求量}
FlowId:
string;{节点流程号}
IngredientId:
string;{节点配方号}
Resolved:
boolean;{是否已分解处理}
end;
//排程的结果所存放的数组(结构见上面的定义)
nodecount1:
integer;
nodes1:
arrayofnoderecord1;
//
//子函数:
根据半成品物料编码和理论需求量,计算其最佳作业需求量的函数...
FunctionTTaskForm.BestNumber(materialId:
string;ProNumber:
real):
real;
var
i:
integer;
oldneed,oknumber,leftnumber,x,oldneed1,addnumber:
real;
begin
try
//得到该物料的原有需求总量...
mandtext:
='SELECTMINNUMBER+PRONEED+PLANNUMBERFROMMATERIALWHEREMATERIALID='''+MaterialId+'''';
oldneed:
=form2.syscommand.execute.Fields[0].Value;
mandtext:
='SELECTMINNUMBER+PLANNUMBERFROMMATERIALWHEREMATERIALID='''+MaterialId+'''';
oldneed1:
=form2.syscommand.execute.Fields[0].Value;
//
//得到本次分解其他结构部分对该物料的需求量...
x:
=0;
fori:
=1tonodecount1do
ifnodes1[i-1].MaterialId=materialidthen
x:
=x+nodes1[i-1].ProNeed;
//
//得到原有供应总量...
mandtext:
=
'SELECTSAVEDNUMBER+WORKSHOPNUMBER+BUYPLANNUMBER+PROPLANNUMBER
FROMMATERIALWHEREMATERIALID='''+MaterialId+'''';
oknumber:
=form2.syscommand.execute.Fields[0].Value;
//
//得到该物料的当前剩余量...
leftnumber:
=oknumber-oldneed-x;
ifleftnumber<0then
begin
ifoknumber addnumber: =oldneed1-oknumber else addnumber: =0; leftnumber: =0; end else addnumber: =0; // //假如理论需求量少于原有剩余量,则本次不新增作业需求量... ifleftnumber>=pronumberthen result: =0 // //否则,理论需求量-原有剩余量=新增作业需求量 else result: =pronumber-leftnumber; // result: =result+addnumber; except result: =pronumber; end; end; // //------------------------------------------------------------------------------------- // //主过程: 根据一个上层部件(或顶层产品)的生产需求量,计算下层各生产工序的最佳作业需求量和各物料的投料需求量的过程,结果保存在nodes1数组中... // //入口参数: //FlowId: 上层部件(或顶层产品)的所属流程号 //StepId: 上层部件(或顶层产品)所在工序号 //ProNumber: 上层部件(或顶层产品)的生产数量(主生产计划) //出口参数: //NodeCount1: 总记录数 //Nodes1: 记录数组,结构见开始处 //其中关键数据: //ProRate: real;{全程投料比例,乘上ProNumber=理论作业需求量} //Number: real;{实际作业需求量} //proneed0: real;{理论投料需求量} //proneed: real;{实际投料需求量} // //说明: 理论作业需求量: 根据BOM直接计算出的工序作业需求量 //实际作业需求量: 在理论作业需求量基础上,再综合所在该工序对应物料的供需平衡 //关系所确定的最佳作业需求量 //理论投料需求量: 根据BOM直接计算出的某个物料即将用于生产的需求量 //实际投料需求量: 根据父件的实际作业需求量计算出的某个物料即将用于生产的需求量 // //生产排程的结果是: 实际作业需求量 //物料需求表的数据来源是: 实际投料需求量 //----------------------------------------------------------------------------------------------------------------------------------- // procedureTTaskForm.ResolveMaterial1(FlowId: string;StepId: string;ProNumber: real); var i,j,k: integer; firststepid: string; tempprorate,tempnumber,proneed,prorate,x: real; begin // //初始化节点表... nodecount1: =1; setlength(nodes1,1); nodes1[0].nodetype: =0;{流程节点} mandtext: ='SELECTTOP1*FROMWORKSTEPWHEREFLOWID='''+flowid+'''ORDERBYSTEPIDDESC'; form2.sysdataset.active: =true; nodes1[0].MaterialId: =trim(form2.sysdataset.fieldbyname('MaterialId').asstring); nodes1[0].MaterialName: =trim(form2.sysdataset.fieldbyname('MaterialName').asstring); nodes1[0].Munit: =trim(form2.sysdataset.fieldbyname('Unit').asstring); nodes1[0].stepid: =''; nodes1[0].stepname: =''; nodes1[0].ProRate: =1.00; nodes1[0].Number: =pronumber; nodes1[0].FlowId: =flowid; nodes1[0].IngredientId: =''; nodes1[0].Resolved: =true;{已分解} form2.sysdataset.active: =false; // //对顶层流程中剩余的工序进行特殊处理... tempprorate: =1.0;{全程投料因子} prorate: =1.0;{继承用投料因子: 即上道工序作业量} tempnumber: =pronumber;{继承用作业量: 即上道工序作业量} // //得到该流程的末端工序编号... mandtext: ='SELECTTOP1STEPIDFROMWORKSTEPWHEREFLOWID='''+flowid+'''ORDERBYSTEPID'; firststepid: =trim(form2.syscommand.execute.fields[0].value); // //过滤出本流程所有剩余工序,从后向前逐个处理... mandtext: ='SELECT*FROMWORKSTEPWHEREFLOWID='''+FlowId+'''ANDSTEPID<='''+stepid+'''ORDERBYSTEPIDDESC'; form2.sysdataset.Active: =true; whilenotform2.sysdataset.eofdo begin // //实际投料需求量=上道工序的作业需求量*本道工序投料比例... iftrim(form2.sysdataset.fieldbyname('MaterialId').asstring)=nodes1[0].MaterialIdthen proneed: =0 else proneed: =tempnumber*prorate; //计算最佳作业需求量(对于顶层物料,实际作业需求量=理论作业需求量) iftrim(form2.sysdataset.fieldbyname('MaterialId').asstring)<>nodes1[0].MaterialIdthen tempnumber: =BestNumber(trim(form2.sysdataset.fieldbyname('MaterialId').asstring),tempnumber*prorate); // //继承本道工序的投料因子到下道工序的处理过程.... prorate: =form2.sysdataset.fieldbyname('ProRate').asfloat; // k: =nodecount1; inc(nodecount1); setlength(nodes1,nodecount1); nodes1[k].nodetype: =2;{半成品节点} nodes1[k].MaterialId: =trim(form2.sysdataset.fieldbyname('MaterialId').asstring); nodes1[k].MaterialName: =trim(form2.sysdataset.fieldbyname('MaterialName').asstring); nodes1[k].MUnit: =trim(form2.sysdataset.fieldbyname('Unit').asstring); nodes1[k].stepid: =trim(form2.sysdataset.fieldbyname('StepId').asstring); nodes1[k].stepname: =trim(form2.sysdataset.fieldbyname('StepName').asstring); nodes1[k].ProRate: =tempprorate;{全程投料因子} nodes1[k].FlowId: =FlowId; nodes1[k].IngredientId: =''; nodes1[k].Resolved: =true; // //保存实际作业需求量与实际投料需求量... nodes1[k].Number: =tempnumber;{实际作业需求量} nodes1[k].proneed: =proneed;{实际投料需求量} // //计算理论投料需求量... iftrim(form2.sysdataset.fieldbyname('MaterialId').asstring)<>nodes1[0].MaterialIdthen nodes1[k].proneed0: =0 else nodes1[k].proneed0: =nodes1[k].ProRate*pronumber;{理论投料需求量} // //假如是末端工序,处理配方连接或流程串接... iftrim(form2.sysdataset.fieldbyname('StepId').asstring)=firststepidthen begin // //假如工序号是00,则生成一个配方节点... ifnodes1[k].stepid='00'then begin k: =nodecount1; inc(nodecount1); setlength(nodes1,nodecount1); nodes1[k].nodetype: =1;{配方接点} nodes1[k].MaterialId: =trim(form2.sysdataset.fieldbyname('OldMaterialId').asstring); nodes1[k].MaterialName: =trim(form2.sysdataset.fieldbyname('OldMaterialName').asstring); nodes1[k].MUnit: =trim(form2.sysdataset.fieldbyname('OldUnit').asstring); nodes1[k].stepid: =''; nodes1[k].stepname: =''; // //从流程继承到配方(由于组装工序产出物料=流程末端原料,因此,直接从上一个节点记录复制数据)... nodes1[k].ProRate: =tempprorate;{与流程末端情况一致} nodes1[k].number: =tempnumber; nodes1[k].proneed: =proneed; nodes1[k].proneed0: =nodes1[k].ProRate*pronumber; // //取配方号... nodes1[k].FlowId: =''; nodes1[k].IngredientId: =trim(form2.sysdataset.fieldbyname('IngredientId').asstring); nodes1[k].Resolved: =false;{未处理} end // //假如工序号不是00,则处理流程串接... else begin // //将当前工序的原材料作为产成品的流程,是要对接的流程... mandtext: ='SELECT*FROMFLOWSWHERETMATERIALID='''+trim(form2.sysdataset.fieldbyname('OldMaterialId').asstring)+''''; form2.tempdataset.active: =true; // //假如不存在对接流程,产生一个原配件接点... ifform2.tempdataset.Eofthen begin form2.tempdataset.active: =false; // k: =nodecount1; inc(nodecount1); setlength(nodes1,nodecount1); nodes1[k].nodetype: =3;{原配件节点} nodes1[k].MaterialId: =trim(form2.sysdataset.fieldbyname('OldMaterialId').asstring); nodes1[k].MaterialName: =trim(form2.sysdataset.fieldbyname('OldMaterialName').asstring); nodes1[k].MUnit: =trim(form2.sysdataset.fieldbyname('OldUnit').asstring); nodes1[k].stepid: =''; nodes1[k].stepname: =''; // //修正全程投料因子... nodes1[k].ProRate: =tempprorate*form2.sysdataset.fieldbyname('ProRate').asfloat; // //原材料的作业需求量为0... nodes1[k].number: =0; // //实际投料需求量=上道工序作业量*本道工序的投料比例... nodes1[k].proneed: =tempnumber*form2.sysdataset.fieldbyname('ProRate').asfloat; // //理论投料需求量计算... nodes1[k].proneed0: =nodes1[k].ProRate*pronumber; // nodes1[k].FlowId: =''; nodes1[k].IngredientId: =''; nodes1[k].Resolved: =true;{已处理} end // //假如存在对接流程,产生一个流程节点... else begin // //计算实际投料需求量... x: =bestnumber(trim(form2.sysdataset.fieldbyname('OldMaterialId').
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 生产 算法