碩士論文-基于Prolog的生產(chǎn)計(jì)劃研究-郭坤_第1頁
碩士論文-基于Prolog的生產(chǎn)計(jì)劃研究-郭坤_第2頁
碩士論文-基于Prolog的生產(chǎn)計(jì)劃研究-郭坤_第3頁
碩士論文-基于Prolog的生產(chǎn)計(jì)劃研究-郭坤_第4頁
碩士論文-基于Prolog的生產(chǎn)計(jì)劃研究-郭坤_第5頁
已閱讀5頁,還剩53頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

中山大學(xué)碩士學(xué)位論文基于Prolog的生產(chǎn)計(jì)劃研究郭坤指導(dǎo)教師:李磊教授專業(yè)名稱:軟件工程單位名稱:軟件學(xué)院答辯委員會(簽名)答辯委員會主席:答辯委員會委員:888基于Prolog的生產(chǎn)計(jì)劃研究專業(yè):軟件工程碩士生:郭坤指導(dǎo)老師:李磊教授中文摘要本文通過對VisualProlog謂詞調(diào)用與接口設(shè)計(jì)的研究,在面向?qū)ο箝_發(fā)語言VisualC#中引入VisualProlog的推理機(jī)制,并將事實(shí)存儲于關(guān)系型數(shù)據(jù)庫中,搭建了一種基于面向?qū)ο笈c面向邏輯編程的混合架構(gòu)有效增強(qiáng)了VisualC#的知識表示能力和VisualProlog的數(shù)據(jù)處理能力。ERP是實(shí)現(xiàn)企業(yè)優(yōu)化管理的有效途徑,生產(chǎn)計(jì)劃是ERP中最重要的組成部分,而BOM數(shù)據(jù)是生產(chǎn)計(jì)劃的基礎(chǔ)?;谂c或樹的BOM結(jié)構(gòu)通過對傳統(tǒng)產(chǎn)品結(jié)構(gòu)樹的擴(kuò)展,既達(dá)到了企業(yè)柔性化設(shè)計(jì)的需求,也滿足BOM數(shù)據(jù)一致性要求,并有效降低了產(chǎn)品變形而引起的數(shù)據(jù)冗余。本文通過對與或樹BOM結(jié)構(gòu)的分枝剪切法生產(chǎn)計(jì)劃的研究,在零件一致性和最小流動資金占用率的約束下,分解主生產(chǎn)計(jì)劃得到需求與或樹,求解所有節(jié)點(diǎn)流動資金占用金額,流動資金占用最少的就是最優(yōu)生產(chǎn)序列。同時(shí),用遞推算法實(shí)現(xiàn)最優(yōu)生產(chǎn)計(jì)劃的制定。最后,本文給出了混合編程架構(gòu)、邏輯模型與生產(chǎn)計(jì)劃的具體實(shí)現(xiàn)。關(guān)鍵詞:面向?qū)ο?,邏輯,ERP,物料清單,生產(chǎn)計(jì)劃,與或樹

ABSTRACT

目錄TOC\o"1-1"\h\z\t"標(biāo)題2,2,ZSU_節(jié),1"中文摘要 ]是基于單一零件在不同產(chǎn)品中是恒定用量的情況下提出的,所以將“單位用量”屬性定義在“部件屬性表”中。然而,針對實(shí)際生產(chǎn)過程中,單一零件在不同產(chǎn)品,其用量是變化的,所以本文是基于零件在不同產(chǎn)品中用量差異的情況下提出的。下面是關(guān)于產(chǎn)品結(jié)構(gòu)與或樹的表結(jié)構(gòu)。表2-4產(chǎn)品結(jié)構(gòu)與或樹BOM表名稱類型含義TreeIDINTEGER樹標(biāo)識NodeIDINTEGER節(jié)點(diǎn)標(biāo)識ProductIDVARCHAR產(chǎn)品編碼ParentIDVARCHAR父件編碼ChildIDVARCHAR子件編碼RelationIDVARCHAR關(guān)系標(biāo)識RelationVARCHAR關(guān)系類型(與、或)QuantityINTEGER數(shù)量表2-5料品屬性表名稱類型含義ProductIDVARCHAR料品編碼ProductNameVARCHAR料品名稱ProductTypeVARCHAR料品類型制造件、采購件、委外件UnitVARCHAR單位TimeINTEGER周期制造件為生產(chǎn)周期采購件為采購周期委外件為委外周期PriceINTEGER單價(jià)制造件為制造費(fèi)用采購件為采購單價(jià)委外件為委外費(fèi)用其中,與或樹節(jié)點(diǎn)表反映的是產(chǎn)品與或樹的結(jié)構(gòu),主鍵是TreeID和NodeID,樹標(biāo)識(TreeID)是節(jié)點(diǎn)所屬與或樹的唯一標(biāo)識,節(jié)點(diǎn)標(biāo)識(NodeID)是對應(yīng)節(jié)點(diǎn)的唯一標(biāo)識。父節(jié)點(diǎn)標(biāo)識(ParentID)指向當(dāng)前節(jié)點(diǎn)的父親節(jié)點(diǎn);關(guān)系標(biāo)識(RelationID)表示節(jié)點(diǎn)間的“與/或”關(guān)系,屬于同一“或”關(guān)系集合的節(jié)點(diǎn)屬于同一關(guān)系(即RelationID的值相同),不同的“與”節(jié)點(diǎn)及不同的“或”關(guān)系節(jié)點(diǎn)集合以不同的關(guān)系(即不同的RelationID)相區(qū)別,其中加入Relation專門用于標(biāo)識當(dāng)前子件的“與或關(guān)系”,這樣的設(shè)計(jì)雖然相對于RelationID是冗余數(shù)據(jù),但在加快系統(tǒng)的處理效率則大有幫助。子件編碼(ChildID)是外鍵,是該節(jié)點(diǎn)所對應(yīng)的部件的料品編碼[NOTEREF_Ref225843649\h9]。在料品屬性表中,通過料品類型(ProductType)來區(qū)別來源,一般分為“制造件、采購件和委外件”三種。周期(Time)根據(jù)不同的為料品類型分別對應(yīng)為“制造周期、采購周期和委外周期”,其中周期是指BOM最頂層裝配(或生產(chǎn))所需時(shí)間,如果要得出某產(chǎn)品實(shí)際的生產(chǎn)周期,則要按照BOM分解至最底層后,逐步累加。單價(jià)(Price)類同于周期,對于不同的料品類型分為對應(yīng)為“制造單價(jià)、采購單價(jià)和委外單價(jià)”,在計(jì)算時(shí)需要按BOM逐層累加。當(dāng)需要修改產(chǎn)品的配置結(jié)構(gòu)時(shí),只需要修改反映結(jié)構(gòu)關(guān)系的與或樹節(jié)點(diǎn)表,更改料品屬性則只需要修改料品屬性表及屬性表間的對應(yīng)關(guān)系。整個(gè)產(chǎn)品的結(jié)構(gòu)可由通過部件代碼關(guān)聯(lián)節(jié)點(diǎn)和屬性表所得到的視圖來反映[NOTEREF_Ref225843704\h5]。 這種設(shè)計(jì)結(jié)構(gòu),取消了必選件表、可選件表和可替換件表,并且解決了可選件在不同產(chǎn)品中的屬性問題,減少了冗余數(shù)據(jù)并有效的提高了系統(tǒng)的處理效率。

第三章基于與或樹BOM的生產(chǎn)計(jì)劃研究3.1引言在上一章我們討論了產(chǎn)品BOM的基本多種結(jié)構(gòu),并且定義了基于與或樹的產(chǎn)品BOM結(jié)構(gòu),在七元組G=(O,A,T,N,E,r,f)中,f是從邊集合E到實(shí)數(shù)集合的函數(shù),對于eE,f(e)是e的權(quán),對權(quán)可用來賦予不同的含義,例如表示子件構(gòu)成父件的數(shù)量、生產(chǎn)成本、生產(chǎn)周期等。那么在研究最優(yōu)生產(chǎn)計(jì)劃時(shí),實(shí)質(zhì)上是研究權(quán)值累加后的最小值或最大值,權(quán)在表示生產(chǎn)成本、生產(chǎn)時(shí)間的情況下,是研究最小值,即:,如果權(quán)在表示利潤的情況下,則是研究最大值,即:。文獻(xiàn)[NOTEREF_Ref225843649\h9]給與或樹的每條邊權(quán)值賦予了生產(chǎn)成本的含義,并定義根節(jié)點(diǎn)具有最小代價(jià)值的子與或樹為最佳與或樹,將面向任務(wù)的產(chǎn)品配置看作為尋找權(quán)值總和最小的子與或樹。然后采用遞推算法實(shí)現(xiàn)了產(chǎn)品的配置。通過文獻(xiàn)[NOTEREF_Ref225843649\h9]定義的最佳子與或樹可以看出,最佳子與或樹必定由全部的“與”節(jié)點(diǎn)及“或”關(guān)系集合中的一個(gè)“或”節(jié)點(diǎn)所組成。文獻(xiàn)[NOTEREF_Ref225843760\h10]在此基礎(chǔ)上提出了最小時(shí)間邊集合在考慮工作中心負(fù)荷的情況下未必是最優(yōu)路徑的觀點(diǎn)。3.2最小流動資金占用率的生產(chǎn)計(jì)劃制定3.2.1生產(chǎn)計(jì)劃制定的約束與目標(biāo)很多生產(chǎn)計(jì)劃都是以最小生產(chǎn)時(shí)間為目標(biāo)的,這是是基于“供小于求”或“供求平衡”的情況下考慮的,這時(shí)候主要是將“生產(chǎn)效率”作為瓶頸來考慮。然而在2008年全球金融危機(jī)的影響下,許多企業(yè)都出現(xiàn)了“供大于求”的現(xiàn)象,甚至于出現(xiàn)已銷售產(chǎn)品無法回收資金的情況,即生產(chǎn)效率不再是瓶頸,此時(shí)的瓶頸就轉(zhuǎn)移了,現(xiàn)在更多的考慮是如何在現(xiàn)有訂單的情況下盡量利用庫存零件,如何在滿足客戶需求的基礎(chǔ)上盡量減少流動資金的占用。這樣對于企業(yè)階段性生產(chǎn)計(jì)劃的目標(biāo)就是盡可能多的保留現(xiàn)金,盤活庫存,并減少流動資金的戰(zhàn)勝,以渡過難關(guān)。本文基于如下約束條件下討論如何減少流動資金占用的問題:約束條件1:同生產(chǎn)批次的產(chǎn)品,其零件必須完全相同,以保證產(chǎn)品一致性;約束條件2:在滿足條件1的情況下,選擇流動資金占用少的零件進(jìn)行生產(chǎn)。3.2.2數(shù)學(xué)模型產(chǎn)品一致性描述:假設(shè)產(chǎn)品P的BOM與或樹為T,實(shí)際生產(chǎn)P時(shí)將采用選擇T的子與或樹t。同生產(chǎn)批次的n個(gè)產(chǎn)品集合P*,對于且,假設(shè)生產(chǎn)Pi的對應(yīng)的子與或樹ti,生產(chǎn)Pj的對應(yīng)的子與或樹tj,要求ti=tj。最小流動資金占用:假設(shè)產(chǎn)品P所有BOM子與或樹t的集合為T,即,R是流動資金占用額r的集合,在生產(chǎn)某批產(chǎn)品時(shí),選取的子與或樹所需要的流動資金,其數(shù)學(xué)模型為:即對于,要求。3.3.2與或樹的生成算法 制定生產(chǎn)計(jì)劃時(shí),我們所選取的“權(quán)邊”是“流動資金占用量”,流動資金占用量=(物料需求數(shù)量–實(shí)際庫存數(shù)量)*單價(jià),所以要分為兩個(gè)步驟進(jìn)行,第一步是根據(jù)BOM分解生成含有“權(quán)”的與或樹,第二步是選取符合要求的子與或樹。算法3.1(偽代碼)GetPlan(){ while(mps.HasNext()==true) { mps.MoveNext(); productID=mps.CductID; //獲取主生產(chǎn)計(jì)劃的產(chǎn)品編碼 quantity=mps.Current.Quantity; //計(jì)劃生產(chǎn)的數(shù)量 GetSubPlan(productID,quantity); }}GetSubPlan(productID,quantity){ storageQuantity=GetStorage(productID); //成品庫存數(shù)量 if(quantity>storageQuantity) { storageQuantity=0; insertPlan(productID,quantity-storageQuantity); //新增計(jì)劃 CheckBom(productID,quantity-storageQuantity); //分解下層BOM }else{//庫存滿足,無需下達(dá)計(jì)劃,要減少庫存 storageQuantity=storageQuantity–quantity;}}CheckBom(productID,quantity){ while(Bom.HasChild(productID)) //存在下層子件 { Bom.MoveNext(); getSubPlan(Bom.Current); //生產(chǎn)下層子件的計(jì)劃,遞歸調(diào)用}}3.3.3最佳子與或樹的遞推算法實(shí)現(xiàn)最佳產(chǎn)品配置就相當(dāng)于求解對應(yīng)的最佳子與或樹,則產(chǎn)品配置算法可等效為搜索對應(yīng)與或樹解圖的方法,求解與或圖解圖的經(jīng)典方法[[]王永慶.人工智能原理和方法.西安:西安交通大學(xué)出版社,2001][]王永慶.人工智能原理和方法.西安:西安交通大學(xué)出版社,2001與或圖搜索的空間和時(shí)間復(fù)雜度與與或圖本身的結(jié)構(gòu)有關(guān),在文獻(xiàn)[[]DechterR.AND/ORSearchSpacesforGraphicalNetwork.TechnicalReport.Universityof[]DechterR.AND/ORSearchSpacesforGraphicalNetwork.TechnicalReport.UniversityofCalifornia,算法3.2(偽代碼)GetBestTree(G,G*){ G*=null; //初始化G*為空 while(G.HasNode()) { Leaf=G.GetAllLeaf(); Leaf.OrderBy(RelationID); //按RelationID排序//取出相同RelationID中Quantity*Price最小的節(jié)點(diǎn) minNode=GetMinCost(RelationID); //刪除其他相同RelationID的節(jié)點(diǎn)及其子節(jié)點(diǎn) G.DeleteNode(RelationID); //更新父節(jié)點(diǎn)的權(quán)邊值 G.UpdateParentNode(minNode); //將當(dāng)前節(jié)點(diǎn)加入新的集合 G*.AddNode(minNode); //從原集合中刪除最小節(jié)點(diǎn) G.DeleteNode(minNode); }}

第四章面向?qū)ο蠛瓦壿嫷幕旌暇幊萄芯?.1引言知識表示是人工智能研究的基本問題之一,通過在VisualC#中引入VisualProlog的推理機(jī)制,可以完善面向?qū)ο笾R表示方法,完善了面向?qū)ο笳Z言的推理功能。VisualProlog具有強(qiáng)大的邏輯推理能力,雖然VisualProlog在新版本中也提供了ODBC訪問接口,但在數(shù)據(jù)庫訪問、數(shù)值計(jì)算和人機(jī)界面處理方面,相較于VisualC#還有差距,事實(shí)上,根據(jù)各種編程語言的優(yōu)勢,同時(shí)合理的使用VisualProlog和其他語言進(jìn)行混合編程,將能夠很好的提高開發(fā)效率和性能[[]徐彤.VisualProlog與VisualC++混合編程技術(shù)研究.空軍工程大學(xué)學(xué)報(bào)(自然科學(xué)版).2006][]徐彤.VisualProlog與VisualC++混合編程技術(shù)研究.空軍工程大學(xué)學(xué)報(bào)(自然科學(xué)版).2006VisualC#基于.NetFramework給軟件開發(fā)提供了豐富的資源,通過使用VisualC#可以開發(fā)出功能強(qiáng)大、擴(kuò)充性好、移植性高的軟件。然而,在大型專家系統(tǒng)中,很少獨(dú)立使用VisualC#來開發(fā),其原因就在于缺乏完善的推理機(jī)制。如果單獨(dú)使用VisualC#來編寫知識庫與推理機(jī)來實(shí)現(xiàn)推理功能,工作量和難度都非常大。研究表明,與Prolog相比,實(shí)現(xiàn)相同的知識表示和推理策略,使用C#要多出10至15倍的代碼。但反過來看,VisualC#在進(jìn)行數(shù)值計(jì)算比VisualProlog方便得多。Prolog只是基于謂詞邏輯的程序設(shè)計(jì)語言,它適合解決推理問題,但是相對于其它傳統(tǒng)語言,數(shù)值計(jì)算并不是它的特長。例如,在數(shù)據(jù)結(jié)構(gòu)中,VisualProlog定義高維數(shù)組非常困難,也不能夠通過下標(biāo)引用數(shù)組元素,這一點(diǎn)不如C#方便靈活。另外,VisualProlog利用遞歸進(jìn)行循環(huán),在單層循環(huán)時(shí)非常簡單,但當(dāng)循環(huán)導(dǎo)數(shù)增多后其編程就比使用VisualC#要困難得多[[]牛奔,哈明虎,王熙照.基于VC和VIP的面向?qū)ο笾R表示.河北科技大學(xué)學(xué)報(bào),2002[]牛奔,哈明虎,王熙照.基于VC和VIP的面向?qū)ο笾R表示.河北科技大學(xué)學(xué)報(bào),20024.2混合編程架構(gòu)設(shè)計(jì)在面向?qū)ο蟪绦蛟O(shè)計(jì)中,數(shù)據(jù)庫主要使用關(guān)系型數(shù)據(jù)庫,如SQLServer和Oracle,在邏輯程序設(shè)計(jì)中,數(shù)據(jù)保存在知識庫中,當(dāng)需要Prolog進(jìn)行推理時(shí),就必須將相應(yīng)的關(guān)系型數(shù)據(jù)從數(shù)據(jù)庫中同步至知識庫中,當(dāng)推理完成,需要將推理結(jié)果轉(zhuǎn)換到數(shù)據(jù)為保存。知識庫數(shù)據(jù)庫知識庫數(shù)據(jù)庫Prolog推理機(jī)C#接口程序推理結(jié)果推理規(guī)則圖4-1混合編程架構(gòu)圖4.3事實(shí)庫的動態(tài)生成與加載 VisualProlog中事實(shí)庫可以在classfacts中聲明,在clauses中定義,比如要定義父子關(guān)系的事實(shí)庫,代碼如下: classfacts father:(stringPerson,stringFather).clauses father(“John”,“Bill”). father(“Bill”,“Mike”). 上述代碼描述這樣的事實(shí),Bill是John的父親,Mike是Bill的父親。 VisualProlog程序是可以編譯成二進(jìn)制文件的,即EXE或DLL文件,如果事實(shí)庫需要事先定義的話,那么就只能硬編碼到程序中了,但作為ERP中的主生產(chǎn)計(jì)劃、BOM、庫存數(shù)據(jù)都不可能是靜態(tài)的硬編碼至VisualProlog推理機(jī)中,所以需要有一種動態(tài)加載的辦法。其實(shí),我們可以將上述代碼中的clauses段完全拷貝至一個(gè)文本文件fact.txt,并將程序中對應(yīng)的clauses段刪除,但classfacts中的聲明還是要保留,然后程序在通過reconsult(“fact.txt”)將事實(shí)動態(tài)加入到程序中,這樣就可以將事實(shí)數(shù)據(jù)與程序分離,并且根據(jù)需要隨時(shí)修改事實(shí)庫了。 然而,真正的ERP基礎(chǔ)數(shù)據(jù)都是存在于關(guān)系型數(shù)據(jù)庫中,那么就需要由VisualC#從數(shù)據(jù)庫讀取需要的數(shù)據(jù)后,按照VisualProlog的語法規(guī)則動態(tài)生成事實(shí)庫文件。 算法4.1(偽代碼) BuildFactsFile(FileName) { ConnectDB(); //連接數(shù)據(jù)庫 OpenDB(); //打開數(shù)據(jù)庫 Result=QueryDB(); //查詢表記錄 F=OpenFile(FileName); //以重寫方式打開文件 WriteLine(“clauses”,F); //寫入第一行 while(Result.HasNext()) { Result.MoveNext(); //寫入事實(shí)庫 WriteLine(“xxx(“+Result.Current[0]+“,”Result.Current[1]+“).”); } CloseDB(); //關(guān)閉數(shù)據(jù)庫 CloseFile(F); //關(guān)閉文件 }4.4事實(shí)庫的讀取與轉(zhuǎn)換 在VisualProlog中的事實(shí)庫,除了可以動態(tài)加載外,也可以通過assert和retract進(jìn)行添加與刪除。當(dāng)修改過后的事實(shí)庫在推理完成后,需要同步至數(shù)據(jù)庫中,此時(shí),就需要將新的事實(shí)庫讀取并轉(zhuǎn)換。在VisualProlog中,可以使用謂詞file::save(stringFileName,factDBFactSection)將事實(shí)庫轉(zhuǎn)存為文本文件,然后通過解析程序?qū)⑽谋疚募械氖聦?shí)分解為獨(dú)立的對象并存入數(shù)據(jù)庫。 算法4.2(偽代碼) ReadFactDB(FileName) { F=OpenFile(FileName); //打開文件 while(F.HasLine()) { //循環(huán)讀取所有記錄 S=F.ReadLine(); //解析S并存入數(shù)據(jù)庫 SaveDB(Split(S)); } CloseFile(FileName); //關(guān)閉文件 } 4.4VisualC#與VisualProlog的接口調(diào)用要在VisualC#中調(diào)用VisualProlog程序進(jìn)行推理,有兩種方法,一是直接調(diào)用VisualProlog編譯的EXE文件,另一種是通過動態(tài)庫DLL來調(diào)用。4.4.1EXE外部程序調(diào)用法 第一步:使用VisualProlog建立新Project(圖4-2)。圖4-2新建Project 第二步:設(shè)置Project屬性,UIStrategy為Console,TargetType為Exe(圖4-3)。圖4-3Project屬性設(shè)置 第三步:編寫VisualProlog代碼。 第四步:編譯源程序,生成Exe文件。 第五步:VisualC#調(diào)用外部EXE應(yīng)用程序的方法,代碼如下:stringexe_path=@"D:\Workspace";System.Diagnostics.Processprocess;process=newSystem.Diagnostics.Process();process.StartInfo.FileName="demo.exe";

process.StartInfo.WorkingDirectory=exe_path;

process.StartInfo.CreateNoWindow=true;

process.Start();

if(process.HasExited)

{

MessageBox.Show("complete");

} 第六步:由于Prolog程序運(yùn)行完成后,要生成一個(gè)事實(shí)庫文件供C#程序讀取,所以調(diào)用EXE時(shí)必須等待外部程序執(zhí)行完畢,此時(shí)需要使用process.WaitForExit()方法將當(dāng)前進(jìn)程堵塞,直到外部進(jìn)程結(jié)束。4.4.2動態(tài)庫調(diào)用法第一步:使用VisualProlog建立新Project(圖4-4)。圖4-4新建Project 第二步:設(shè)置Project屬性,UIStrategy為Console,TargetType為Dll(圖4-5)。圖4-5Project屬性設(shè)置第三步:在cl文件中定義需要調(diào)用的謂詞。demo:()

procedure()

language

stdcall

as

"demo". 第四步:在pro文件clauses段中編寫推理代碼。第五步:編譯生成DLL文件。第六步:在VisualC#中定義要調(diào)用的api。[DllImport("BOMLib.dll",EntryPoint="demo")]staticexternvoiddemo(); 第七步:在VisualC#代碼中直接調(diào)用demo方法進(jìn)行推理。4.4.3調(diào)用方法的選擇 外部EXE程序調(diào)用法,實(shí)現(xiàn)起來簡單方便,但與主程序從進(jìn)程上是分離的。DLL調(diào)用法實(shí)現(xiàn)相對復(fù)雜,但它必須附加于主進(jìn)程才可運(yùn)行,從進(jìn)程管理和內(nèi)存分配來看,這是一種更為統(tǒng)一和優(yōu)雅的方法。所以本文選擇DLL調(diào)用法來進(jìn)行VisualC#與VisualProlog的接口調(diào)用。

第五章系統(tǒng)設(shè)計(jì)5.1系統(tǒng)的總體設(shè)計(jì)系統(tǒng)分為兩個(gè)部分,一是邏輯推理程序,二是接口轉(zhuǎn)換程序。邏輯推理程序使用VisualProlog開發(fā),用于事實(shí)庫的分析,得出需求與或樹;接口轉(zhuǎn)換程序使用VisualC#開發(fā),用于事實(shí)庫與數(shù)據(jù)庫的轉(zhuǎn)換,以及結(jié)果的顯示。5.2靜態(tài)類圖

第六章系統(tǒng)的實(shí)現(xiàn)和應(yīng)用6.1生產(chǎn)計(jì)劃的邏輯描述與實(shí)現(xiàn)6.1.1VisualProlog相關(guān)技術(shù)邏輯程序設(shè)計(jì)語言VisualProlog是一種說明性的程序語言,是基于一階謂詞邏輯的,正因?yàn)榇耍褂盟軌虮绕渌恼Z言更快速地開發(fā)程序,因?yàn)樗木幊谭椒ǜ笫鞘褂眠壿嫷恼Z言來描述程序[[]李磊.[]李磊.邏輯程序設(shè)計(jì)與數(shù)據(jù)庫.中山大學(xué)軟件所VisualProlog是基于Horn子句邏輯的。Horn子句邏輯是對事物及其相互關(guān)系進(jìn)行推理的形式系統(tǒng)。VisualProlog程序由一系列的事實(shí)與規(guī)則構(gòu)成,通過回溯來完成推理。回溯機(jī)制是邏輯程序設(shè)計(jì)的重要設(shè)施?;厮荼旧硎且环N獲得目標(biāo)所有可能解的良好方法?;厮菔侵甘镜胶翁幦ふ覇栴}答案的機(jī)制。這種機(jī)制使得VisualProlog具有了通過所有已知事實(shí)和規(guī)則進(jìn)行搜索求解的能力。合一(unification)是與回溯機(jī)制密切相關(guān)的一個(gè)重要概念。當(dāng)VisualProlog試圖執(zhí)行一個(gè)子目標(biāo)written_by(X,Y)時(shí),為了在程序中獲得匹配,必須測試每一個(gè)written_by子句。在嘗試把參數(shù)X和Y與每一個(gè)written_by子句的參數(shù)進(jìn)行匹配時(shí),VisualProlog將從頭至尾對程序進(jìn)行搜索。當(dāng)它找到匹配目標(biāo)的子句時(shí),將數(shù)值綁定到自由變量,以便使目標(biāo)和子句是同一的;目標(biāo)被稱為與子句合一(unify)。這一匹配操作就叫做合一。所謂回溯(backtrack),是指使用“回退再試”對給定問題找到所有可能解的一種方法。當(dāng)VisualProlog開始為求解一個(gè)問題(或目標(biāo))尋找答案時(shí),往往要在多種可能情況中做出抉擇。它首先在分支點(diǎn)(即回溯點(diǎn))設(shè)置好標(biāo)志,然后選擇要追蹤的第一個(gè)子目標(biāo)。如果該子目標(biāo)失敗,VisualProlog將回退到上一個(gè)回溯點(diǎn)嘗試另一個(gè)目標(biāo)[[]雷英杰,王濤,趙曄,王建勛.VisualProlog的回溯機(jī)制分析.空軍工程大學(xué)學(xué)報(bào)(自然科學(xué)版),2004,5(5),80-84][]雷英杰,王濤,趙曄,王建勛.VisualProlog的回溯機(jī)制分析.空軍工程大學(xué)學(xué)報(bào)(自然科學(xué)版),2004,5(5),80-846.1.2物料需求計(jì)劃的邏輯實(shí)現(xiàn)在運(yùn)算物料需求計(jì)劃之前,必須建立相關(guān)事實(shí)庫,根據(jù)計(jì)算的要求,需要定義料品事實(shí),包括料品編碼、料品類型、(制造/采購/委外)周期和單價(jià);BOM事實(shí),包括料品編碼、關(guān)系序號、關(guān)系、父件編碼、子件編碼和數(shù)量;庫存事實(shí),包括料品編碼、庫存數(shù)量;主生產(chǎn)計(jì)劃事實(shí),包括計(jì)劃序號、產(chǎn)品編碼和計(jì)劃數(shù)量。具體定義如下:classfacts-baseFactsDB%product(ProductID,ProductType,Days,Price)product:(string,productType,integer,integer).%bom(ProductID,RelationID,Relation,ParentID,ChildID,Quantity)bom:(string,string,string,string,string,integer).%storage(ProductID,Quantity)storage:(string,integer).%mps(MpsID,ProductID,Quantity)mps:(string,string,integer).事實(shí)都保存在關(guān)系數(shù)據(jù)庫SQLServer中,當(dāng)接口程序通過數(shù)據(jù)庫操作將記錄導(dǎo)出為事實(shí)庫數(shù)據(jù)文件后,再由推理程序動態(tài)加載事實(shí)庫。謂詞reconsult定義如下:%動態(tài)加載事實(shí)庫

class

predicates

reconsult:(string

FileName).

clauses

reconsult(FileName):-

%retractAll(_,factsDB),

file::consult(FileName,baseFactsDB) 在進(jìn)行計(jì)算時(shí),需要讀取物料的基本屬性與庫存信息,謂詞getProductInfo和getStorage定義如下:classpredicates getProductInfo:(stringProductID,stringProductType,integerDays,integerPrice)nondeterm(i,o,o,o).clausesgetProductInfo(ProductID,ProductType,Days,Price):-product(ProductID,manType(),SDays,SPrice),!,ProductType="mantype",Days=SDays,Price=SPrice.getProductInfo(ProductID,ProductType,Days,Price):-product(ProductID,purType(),SDays,SPrice),!,ProductType="purtype",Days=SDays,Price=SPrice.getProductInfo(ProductID,ProductType,Days,Price):-product(ProductID,outType(),SDays,SPrice),!,ProductType="outtype",Days=SDays,Price=SPrice.classpredicatesgetStorage:(stringProductID,integerStorageQuantity)determ(i,o).clausesgetStorage(ProductID,StorageQuantity):-if(storage(ProductID,SQuantity),!)then%存在庫存,直接返回StorageQuantity=SQuantityelse%不存在庫存StorageQuantity=0endif.由于在分解過程中,當(dāng)某個(gè)物料有需求時(shí),要先使用現(xiàn)有庫存,再下達(dá)需求計(jì)劃,這需要動態(tài)鎖定已用庫存,此處通過修改現(xiàn)有庫存數(shù)量的方式來鎖定庫存。謂詞modifStorage定義如下:classpredicates%修改庫存modifyStorage:(stringProductID,integerStorageQuantity)nondeterm(i,i).clausesmodifyStorage(ProductID,StorageQuantity):-if(storage(ProductID,SQuantity),!)then%查找到庫存記錄retract(storage(Product,SQuantity)),%插入新記錄if(StorageQuantity>0)thenassert(storage(Product,StorageQuantity))endifendif.循環(huán)讀取主生產(chǎn)計(jì)劃(MPS),然后從上至下按BOM逐層分解,計(jì)算物料需求。謂詞getPlan、getSubPlan和checkBom定義如下:%產(chǎn)生第一層的凈需求classpredicatesgetPlan:()nondetermanyflow.clausesgetPlan():-mps(MpsID,ProductID,Quantity),getSubPlan(MpsID,ProductID,"","and","",ProductID,Quantity,0),fail.classpredicatesgetSubPlan:(stringMpsID,stringProductID,stringRelationID,stringRelation,stringParentID,stringChildID,integerQuantity,integerDays)nondeterm(i,i,i,i,i,i,i,i).clausesgetSubPlan(MpsID,ProductID,RelationID,Relation,ParentID,ChildID,Quantity,Days):-%首次添加%要先查詢出物料類型getProductInfo(ChildID,ProductType,ProductDays,Price),%查詢當(dāng)前庫存getStorage(ChildID,StorageQuantity),%使用當(dāng)前庫存并修改庫存if(Quantity>StorageQuantity)then%需求量大于庫存數(shù)modifyStorage(ProductID,0),%插入計(jì)劃isLeaf(ProductID,ChildID,IsLeafValue),assert(plan(MpsID,ProductID,RelationID,Relation,ParentID,ChildID,Quantity-StorageQuantity,Days+ProductDays,IsLeafValue,(Quantity-StorageQuantity)*Price)),%分解BOM并計(jì)算子件需求checkBom(ProductType,MpsID,ProductID,ChildID,Quantity-StorageQuantity,Days+ProductDays)else%需求量小于等于庫存數(shù),不需要下達(dá)計(jì)劃modifyStorage(ProductID,StorageQuantity-Quantity),isLeaf(ProductID,ChildID,IsLeafValue),assert(plan(MpsID,ProductID,RelationID,Relation,ParentID,ChildID,0,Days+ProductDays,IsLeafValue,0))endif.classpredicatescheckBom:(stringProductType,stringMpsID,stringProductID,stringParentID,integerQuantity,integerDays)nondeterm(i,i,i,i,i,i).clausescheckBom(ProductType,MpsID,ProductID,ParentID,Quantity,Days):-%檢查是否有下層物料bom(ProductID,RelationID,Relation,ParentID,ChildID,SubQuantity),getSubPlan(MpsID,ProductID,RelationID,Relation,ParentID,ChildID,SubQuantity*Quantity,Days),fail.6.1.3最優(yōu)生產(chǎn)計(jì)劃的實(shí)現(xiàn)GetBestTree()為獲取最優(yōu)化子與或樹的代碼,F(xiàn)illBestTree()將得到的最優(yōu)結(jié)果填寫至界面中顯示出來,SetLeaf()是尋找與或樹的葉子節(jié)點(diǎn),UpdateParentPlan()是所選出的最優(yōu)節(jié)點(diǎn)的價(jià)格反填至父件價(jià)格。privateArrayListGetBestTree(){stringfileName=AppDomain.CurrentDomain.BaseDirectory+"\\Result.txt";ArrayListplans=PlanManager.GetInstance().GetPlansFromFile(fileName);ArrayListplanLeaf=newArrayList();ArrayListplansTree=newArrayList();while(plans.Count>0){//將所有葉子節(jié)點(diǎn)存入planLeafSetLeaf(plans);for(inti=plans.Count-1;i>=0;i--){Planplan=(Plan)plans[i];if(plan.IsLeaf){planLeaf.Add(plan);plans.RemoveAt(i);}}//比較葉子節(jié)點(diǎn),選擇較小代價(jià)的節(jié)點(diǎn)保留for(inti=planLeaf.Count-1;i>=0;i--){PlancurPlan=(Plan)planLeaf[i];curPlan.BestLeaf=1;if(curPlan.Relation.Equals("and")||curPlan.Relation.Equals("")){//不進(jìn)行處理}else{for(intj=0;j<planLeaf.Count;j++){Planplan=(Plan)planLeaf[j];if(curPlan.RelationID.Equals(plan.RelationID)&&curPlan.ChildID.Equals(plan.ChildID)==false){if(curPlan.Price>plan.Price){curPlan.BestLeaf=0;plan.BestLeaf=1;curPlan=plan;}else{plan.BestLeaf=0;}}}}}for(inti=planLeaf.Count-1;i>=0;i--){PlancurPlan=(Plan)planLeaf[i];if(curPlan.BestLeaf==1){//表示為最優(yōu)節(jié)點(diǎn)planLeaf.Remove(curPlan);plansTree.Add(curPlan);UpdateParentPlan(curPlan,plans);}elseif(curPlan.BestLeaf==0){//較差節(jié)點(diǎn)planLeaf.Remove(curPlan);} } }return(plansTree);}privatevoidFillBestTree(ArrayListin_Plans){for(inti=0;i<in_Plans.Count;i++){Planplan=(Plan)in_Plans[i];ListViewItemitem=newListViewItem();item.Text=plan.MpsID;stringplanType="";if(plan.PlanType.Equals("mantype")){planType="制造計(jì)劃";}elseif(plan.PlanType.Equals("purtype")){planType="采購計(jì)劃";}elseif(plan.PlanType.Equals("outtype")){planType="委外計(jì)劃";}item.SubItems.Add(planType);item.SubItems.Add(plan.ProductID);item.SubItems.Add(plan.RelationID);item.SubItems.Add(plan.Relation);item.SubItems.Add(plan.ParentID);item.SubItems.Add(plan.ChildID);item.SubItems.Add(plan.Quantity.ToString());item.SubItems.Add(plan.Price.ToString());item.SubItems.Add(plan.StartDate.ToString("yyyy-MM-dd"));item.SubItems.Add(plan.EndDate.ToString("yyyy-MM-dd"));lstBestTree.Items.Add(item);}}privatevoidSetLeaf(ArrayListin_Plans){for(inti=0;i<in_Plans.Count;i++){Planplan=(Plan)in_Plans[i];plan.IsLeaf=true;for(intj=0;j<in_Plans.Count;j++){PlancomparePlan=(Plan)in_Plans[j];if(comparePlan.ParentID.Equals(plan.ChildID)){plan.IsLeaf=false;break;}}}}privatevoidUpdateParentPlan(Planin_Plan,ArrayListin_Plans){for(inti=0;i<in_Plans.Count;i++){Planplan=(Plan)in_Plans[i];if(plan.MpsID.Equals(in_Plan.MpsID)&&plan.ChildID.Equals(in_Plan.ParentID)){plan.Price=plan.Price+in_Plan.Price;break;}}}6.2事實(shí)庫導(dǎo)入導(dǎo)出的具體實(shí)現(xiàn)6.2.1表結(jié)構(gòu)設(shè)計(jì)本文涉及到主要數(shù)據(jù)表有物料表(Product)、庫存表(Storage)、物料清單表(Bom)和主生產(chǎn)計(jì)劃表(Mps),具體表結(jié)構(gòu)與鍵設(shè)置見圖5-1。圖5-1ER圖6.2.2動態(tài)生成事實(shí)庫 在調(diào)用推理機(jī)前,先將數(shù)據(jù)庫存放事實(shí)的表(包括Product、Bom、Mps和Storage)通過數(shù)據(jù)庫訪問對象讀取出來,并根據(jù)VisualProlog的語法規(guī)則生成相應(yīng)的事實(shí)庫文件,供推理機(jī)動態(tài)加載。具體代碼如下:/***生成Product事實(shí)庫**/publicvoidAssertFactsDB(stringin_FactsFileName){//打開文件并進(jìn)行添加FileStreamfs=newFileStream(in_FactsFileName,FileMode.Append);StreamWritersw=newStreamWriter(fs);DataSetds=GetProductDataSet();if(ds.Tables[TableName]!=null){DataTabletable=ds.Tables[TableName];for(inti=0;i<table.Rows.Count;i++){//循環(huán)取出記錄并轉(zhuǎn)換為Product對象DataRowrow=table.Rows[i];stringproductID=row["ProductID"].ToString();stringproductName=row["ProductName"].ToString();stringproductType=row["ProductType"].ToString();intproductTime=int.Parse(row["ProductTime"].ToString());intprice=int.Parse(row["Price"].ToString());stringfacts="product(\""+productID+"\","+productType+"(),"+productTime+","+price+").";sw.WriteLine(facts);}}sw.Flush();sw.Close();fs.Close();}/***生成Bom事實(shí)庫**/publicvoidAssertFactsDB(stringin_FactsFileName){//打開文件并進(jìn)行添加FileStreamfs=newFileStream(in_FactsFileName,FileMode.Append);StreamWritersw=newStreamWriter(fs);DataSetds=GetBomDataSet();if(ds.Tables[TableName]!=null){DataTabletable=ds.Tables[TableName];for(inti=0;i<table.Rows.Count;i++){//循環(huán)取出記錄并轉(zhuǎn)換為Product對象DataRowrow=table.Rows[i];stringproductID=row["ProductID"].ToString();stringrelationID=row["RelationID"].ToString();stringrelation=row["Relation"].ToString();stringparentID=row["ParentID"].ToString();stringchildID=row["ChildID"].ToString();stringquantity=row["Quantity"].ToString();stringfacts="bom(\""+productID+"\",\""+relationID+"\",\""+relation+"\",\""+parentID+"\",\""+childID+"\","+quantity+").";sw.WriteLine(facts);}}sw.Flush();sw.Close();fs.Close();}/***生成Mps事實(shí)庫**/publicvoidAssertFactsDB(stringin_FactsFileName){//打開文件并進(jìn)行添加FileStreamfs=newFileStream(in_FactsFileName,FileMode.Append);StreamWritersw=newStreamWriter(fs);DataSetds=GetMpsDataSet();if(ds.Tables[TableName]!=null){DataTabletabl

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論