Optaplanner規劃引擎的工作原理及簡單示例(1)

  在之前的文章中,老猿已介紹過APS及規劃的相關內容,也對Optaplanner相關的概念和一些使用示例進行過介紹,接下來的文章中,我會自己做一個規劃小程序 - 一個關于把任務分配到不同的機臺上進行作來的小程序,并在這個小程序的基礎上對Optaplanner中更多的概念,功能,及使用方法進行講解。但在此之前,我需要先講解一下Optaplanner在運行規則運算的原理。所以,本文是講述一些關于尋找最優解的過程中的原理性的內容,作為后續通過示例深入講解的基礎。但這些原理知識不會涉及過分深奧的數學算法,畢竟我們的目標不是寫一個新的規劃引擎出來,只是理解一些概念,用于理解Optaplanner是依據什么找出一個相對優解的。好讓在接下來的一系列文章中,可以快速無障礙地理解我所講解的更細化的Optaplanner功能。

  好了,言歸正傳,本文主要是講述Optaplanner是如何在用戶定義的規則限制條件中,基于約束的限制,對被規劃對象進行排列組合,再對比各個組合(稱作解,或方案),并找出相對最優的解出來。在這個尋優過程中,Optaplanner會使用到一些相關算法,例如啟發式算法(例如First Fit)和延遲接受法(例如禁忌搜索),從而提高尋找相對最優解的效率和防止嵌入局部最優解,從而可以在固定的時間內,找到盡可能優的方案。

  在理解Optapalnner是如何實現之前,我們先復習并展開一下上一篇提到的概念 - 約束。

約束(Constraint):

  也就是對事物的一種限制,規定事物的發展應該遵循什么規則,具體到Optaplanner里,就是用于表達出什么是對的,什么是錯的,什么情況是最優,什么情況次優,什么情況較差。從而讓引擎得到各個解的對比依據。

  在Optapalnner中的約束可以分為硬約束軟約束兩種,其實還有更多的約束類型 ,例如中間約束,甚至是無限層級的約束,但總結起來,其作用也就是把約束劃分為不同層級,從而區分出不同的優等級而已,如果有軟件開發經驗的同學,可以理解不同層級的約束,分別是SQL語句里Order By子句后面的字段次序。在進行記錄排序時,前面的字段排列的優先級,是從性質上優先于后面的字段的,大家理解了Order By子句,也就理解了不同層級約束的問題了。拉下來我們以最簡單的軟硬約束,來分析一下約束的作用。

硬約束:

  硬約束是用來規定什么情況是對的,什么情況是錯的;什么組合是好的,什么組合是不好的......也就是它通常是用來對所得的解進行一些定性的狀態定義。例如一個計劃是否可行,例如會不會同一個機臺同一個時間分配了兩個不同的任務(假設每個機臺同時只能做同一個任務)。一個員工所排班次是否正確(例如一個員工是否被安排了三個連續的班次)。若出現上種情況,即表示違反了硬約束,這種方案稱作不可行方案。以后的文章里,會提到Optaplanner里有一個明確的概念 - Feasable Solution(可行方案,或稱可行解),就是表示這個方案是完全符合硬約束的。

軟約束:

  軟約束規定什么情況最優,什么情況次優,什么情況是差的;它是用來定義方案優劣的定量狀態。例如:一個計劃的成本是否足夠低;一個排班表到底有多大程度上的合理性,例如一個人正常情況下是需要5天工作制的,但如果遇到特殊情況,也可以連續工作6天,但這種情況是特殊的,需要額外付加班費(成本上升)最好不要出現這種情況。那么在編制這個排班表的時候,如果有一個方案是需要有人員連續工作6天,但如果找到另一個方案,可以令所有人均不需要連續工作6天,那么,后面這個方案就比那些有人需要連續工作6天的方案更好了。體現在軟約束上,就是后面的排產表,其軟約束上會比前一個排班表更好,違反的軟約束更少。

  上述講述的是兩種常見約束,那么這些約束在Optaplanner里是如何生效的呢?那說需要有一種評分機制了,也是我們在使用Optaplanner里,比較難準確把握的一個內容之一。

評分機制:評分是用分數來評價事物特性的一種方法。但如果我們細心觀察總結一下,會發現評份是可以通過兩種方向來評價的;分別是正評分(獎勵性評分)和負評分(懲罰性評分)。

正評分:通過獲得分數的多少,來體現事物的優劣。例如我們在學校考試過程中,成績是通過一種正分數來體現的,即做對一題獎勵相應的分數,分數越高成績越好;完美狀態是獲得滿分。

負評分:通過扣除分數的多少,來體現事物的優劣。例如我們的駕駛證記分制,每違章一次就扣除相應的分數,很明顯這種評份體系中,分數越低越好,也就是扣得越少越好;完美狀態是扣0分。

  在對實際問題進行約束規劃時,是一種封閉性約束,也就是約定事物往指定的一個方向發現,使用負評分的方式,很顯然更合理。也就是一個方案有哪些不好的,我們通過對它評定一些懲罰分數標準,告訴引擎這種組合出現了一些不太好的情況。如此類推,每找到一個更佳、扣分更少的方案,就離完美就更近一步。無論是使用正方向評份還是反方向評分(或稱負方向評分),在Optaplanner里都是可以實現的,只不過按我們日常的邏輯,在定義方案時,通常我們只會根據業務定義出一些規則,方案是需要守這些規則,當一個方案出現有違反規則時,就作出相應的懲罰性扣分;這種方法比當出現好的情況就加分更合理。因為我們的現實世界里,"好"是可能無限好的,當問題足夠復雜,數據量足夠大,即問題規模夠大時,描述一個方案如何個好法,其實很難是一個定數。比描述一個方案如何個差法更難,因為前者可以是無限的,而后都就只需要我們定義好什么是差的標準,一但問題范圍確定,它的最差情況(也就是最差的扣分情況)就有一個字數了。所以,在Optaplanner的世界里,常見的做法是,定義一些約束,并設定相應的懲罰分數標準(即將約束量化),用來描述這個方案的制約因素,當這個約束實打破時,就作出懲罰性記分,那么到最后,扣分越少的方案就越好。這就是Optaplanner實現尋優的最基本原理,但其實現是非常復雜的,會將問題劃分為很多種類,將尋優的過程劃分為多個階段,每個階段利用不同種類的算法來提高找到更優方案的效率,每個階段有很多個步驟,每個步驟又有多個移動(沒錯,Optaplanner里就有Step與Move的概念,以后會詳解);在以后的深入文章中,我會詳細把這個過程分析出來。

  上面描述了硬約束、軟約束和評份機制。那么如何將這兩種約束與這種評分機制關聯起來,令評分機制可以實現軟、硬約束呢?大家可能已想到,在Optaplanner給出了軟分數,硬分數的概念。在評分機制中,當出現一個方案違反了某個硬約束時,就給這個方案扣除這個約束相應的分數;同樣地,當該方案違反了一種軟約束時,就對該方案扣除該軟約束相應的分數。這兩個分數是分開處理的。因為通過它們對應的約束類別就知道,它們分別代表的性質不一樣,硬分數對應的硬約束,代表的是一種定性評價;即描述方案好不好,行不行,可不可取等,一旦被記扣硬分數,那就表示這個方案的性質就變了,由可行方案變成不可行方案。理想的方案是一個硬分都不能扣的,一旦扣了就是不可行方案了。有人問,那么定義硬分數的分值有什么用?直接給一個標識出來,將方案的可用性定義為True or False,分別代表是事有硬約束被違反不就行了嗎,多簡單呀,因為一旦為False就是不可用了,再去討論它扣了多少分,又有何意義呢?硬約束、硬分數不就是為了給方案定性而設立的嗎?何必還要記錄它的扣分量,多此一舉呢?

  如果這樣想,就是一種不全面的想法了。因為大家需要明白,現實世界往往是很大程度是不完美的,但而對不完美,我們是放棄這個世界,還是在不完美中進行堅持,對這個不完美的世界,朝完美的方向進行改造呢?上面的說法就比較抽象比較虛了,舉個大家容易理解的例子。例如:刑法是用來懲罰犯罪的,在正常的法治社會中,犯罪對于一個人說,就相當于違反了硬約束(刑事處罰記錄是終身跟隨的)。也就是對于一個人來說,一生中是否觸犯過刑法,是一個定性的問題。那么既然是定性問題,我們在設立刑法的時候,其對應的懲罰是不是只有一種就足夠了呢?例如凡是觸犯刑法,全部判死刑,那不就簡單得多啦?事實上人類社會是不可能這樣的,因為就算是觸犯了刑法(這個已經是定性問題),但罪行也有輕重之分的、對應了刑法的不同條款,有些罪名經過對罪犯的懲戒,是可以再給他一次機會的,也說就是說觸犯的刑法,是有輕重之分的,但性質不會變,他在國家司法機關的檔案里,永遠留有普被刑事處理的記錄。所以,這可以稱該種情況為定性范圍內的定量問題。就是一個人做錯了就是錯了,其性質已經定了,但犯的錯誤有多大,還得是一個定量問題。因此,硬約束對應的扣除硬的分數有多有少就不難理解了。就是我們的方案如果出現了違反硬約束、被扣除了硬分數的,它在Optaplanner上就是一個不可行方案了。但是在眾多的不可行方案里,其實還要區分哪個是更不可行,哪些其實只是違反了一點點,還是“稍為可行的”。回到我們的實際排程問題中,有可能客觀條件限制,我們所有排出來的方案(例如生產計劃、排班表、車輛調試線路圖)都是不可行的,例如:我們排生產計劃的時候,將交貨期延誤作為一種硬約束,但是現實的生產活動中,確確實實有可能無論你怎么排,因為產能、資源限制等因素,你是不可能找到一個完完全全符合交期的生產計劃的,那么這個時間我們就需要找出一個違反得最小的計劃出來,作為可行計劃,視情況進行相應的修改并執行了。也就是說兩害相遇取其輕。

  對于硬約束,除了上述講到,當出現有可能確實需要使用不可行方案作為執行計劃的情況外,在Optaplanner進行規則的過程中,其實也起到非常大作用的。先不說optaplanner引來來排程;如果讓你來排,對于各種硬約束,全都不給出一個分數,而是給一個定性的標識,就是一旦出現違反了,就報一個違反硬約束的消息出來,你會怎么樣?你肯定會抱怨提示的信息太簡陋了,只有一個標識,最多只是知道哪里違反了,再也沒有更詳細的信息供你參考了。那你接下來的排產活動,其實就是一個組合一個組合逐一地去碰彩了。因為各個方案之間是否有關聯,你是無法得知的,所以你根本找不到什么好的辦法去將各種情況下的方案進行歸類、比較進行往指定的一個方向收斂。但如果在一個硬約束被違反時,會出現一些明確的信息,是哪個硬約束被違反了。違反和程度是多少,扣了多少分,是因為哪個被規則的對象,放在哪里,或與哪個對象相鄰從而導致的硬約束被違反。這樣就形成了一個很明確指導方向,對于人而言,通過歸納統計就知道某些情況肯定會出現,或極大可能會出現違反硬約束的情況,那我們就可以在排列新方案時,盡力去避免這種情況了;也就是有了參考方向 。對于Optaplanner引擎來說也是同理,盡管它不像人這么聰明(但最從近的消息來看,Optapalnner團隊已經著手思考人工智能引入到引擎中,從而實現如上述人類一樣對這類問題進行歸納思考),但也能夠作為其尋找更佳方案的過程中的一些很重要的參考,從而為尋優算法所用,進而提高尋優效率。例如遺傳算法。

  軟分數對應的軟約束,代表的是一種定量評價;即描述方案有多好、有多差,成本有多高、有多低。它是一種優化約束,即在定義它的時候,就已經知道它必然是被違反的(也有可能完全不違反,那當然是好的,但如果是這樣的話,就脫離了軟約束的初充了)。所以,軟件約束、軟件分數的扣分值用途相對來說就容易理解得多了。

  ?綜上所述,Optaplanner就是通過一種體現為分數的約束機制,進行尋找最優組合。當一個排產問題中,設定的軟硬兩種約束時,它會優先滿足硬約束的要求,再滿足軟約束的要求,也就是說,軟約束被扣為1萬分,也不及硬約束被扣了1分重要,聯系上面的SQL語句中的Order By子句的例子。

  Optaplanner其利用途徑有以下兩點:

1. 用分數來確定,一個方案是否可行,是優是劣;

2. 在決定每一步的時候,參考上一點的扣分情況,來確定下一次生成方法時,應該考慮哪此因素(想想遺傳算法).

  這一篇我們先講解一下原理,打一下基礎,下一篇將用一個任務與機臺的例子來說明一下這些原理在Optaplanner中是如何體現的。

?

一個IT老農,先盡力好當兒子、丈夫和父親的責任,然后做點有趣的事。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282877.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282877.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282877.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[HNOI2017]禮物

題目描述 我的室友最近喜歡上了一個可愛的小女生。馬上就要到她的生日了,他決定買一對情侶手環,一個留給自己,一個送給她。每個手環上各有 n 個裝飾物,并且每個裝飾物都有一定的亮度。 但是在她生日的前一天,我的室友突…

《ASP.NET Core 6框架揭秘》實例演示[25]:配置與承載環境的應用

與服務注冊一樣,針對配置的設置同樣可以采用三種不同的編程模式。第一種是利用WebApplicationBuilder的Host屬性返回的IHostBuilder對象,它可以幫助我們設置面向宿主和應用的配置。IWebHostBuilder接口上面同樣提供了一系列用來對配置進行設置的方法&…

oracle的除,Oracle數據庫如何去除別名 - daiyan0526的個人空間 - 51Testing軟件測試網 51Testing軟件測試網-軟件測試人的精神家園...

本人曾經用Personal OracleDeveloper2000開發了一些程序,當移植到FOR NT的時候發現有些功能出現了出錯提示。經研究發現原來是用戶沒有能正常連接。由于在developer2000連接personal oracle時不需要別名(alias),直接寫入用戶名/密碼則可。而在OracleFOR …

Java 之 JavaScript (一)

1.JavaScripta.定義&#xff1a;JavaScript是腳本語言&#xff0c;是一種輕量級的編程語言b.實現&#xff1a;①直接通過標簽里面的onXX屬性驅動js的執行<input type"button" value"測試" οnclick"alert(‘hello‘)">②引入外部js文件——…

Linux日志出現大量kernel: NET: Registered protocol family 36

一臺Linux服務器的系統錯誤日志出現大量的“ kernel: NET: Registered protocol family 36”錯誤信息&#xff0c;如下所示&#xff1a; Jul 2 05:27:45 xxxxxx kernel: NET: Registered protocol family 36Jul 2 05:27:45 xxxxxx kernel: NET: Unregistered protocol family…

node的模塊機制

Node.js模塊的實現 之前在網上查閱了許多介紹Node.js的文章&#xff0c;可惜對于Node.js的模塊機制大都著墨不多。在后續介紹模塊的使用之前&#xff0c;我認為有必要深入一下Node.js的模塊機制。 CommonJS規范 早在Netscape誕生不久后&#xff0c;JavaScript就一直在探索本地編…

vs使用ado連接oracle,在VS環境下以ADO方式操作Oracle數據庫

利用ADO引擎方式訪問Oracle數據庫的實現方法&#xff1a;定義數據庫頭文件為CDBOperation.h#pragma once#import "C:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF","adoEOF"),rename("LockTypeEnum"…

httpstat:一個檢查網站性能的 curl 統計分析工具

httpstat&#xff1a;一個檢查網站性能的 curl 統計分析工具httpstat 是一個 Python 腳本&#xff0c;它以美妙妥善的方式反映了 curl 統計分析&#xff0c;它是一個單一腳本&#xff0c;兼容 Python 3 &#xff0c;在用戶的系統上不需要安裝額外的軟件(依賴)。作者&#xff1a…

Unity(創建腳本)

#一、描述 記錄第一課時&#xff0c;腳本的創建與使用基本的API #二、學習記錄 &#xff08;一&#xff09;創建一個Cube方塊 &#xff08;二&#xff09;在cube組件上添加一個腳本&#xff0c;選中cube組件&#xff0c;在屏幕右側有著cube的組件屬性欄&#xff0c;點擊AddComp…

關于面試中看到一些問題

最近公司在招聘.NET開發人員&#xff0c;面試了一些人&#xff0c;有一些感悟&#xff0c;分享出來&#xff0c;以供參考。面試的人員中&#xff0c;有一些是三五年的開發人員&#xff1b;也有幾個是10年左右的技術負責人&#xff0c;不但自己架構過項目&#xff0c;還有帶領導…

jQuery遍歷not的用法

從包含所有段落的集合中刪除 id 為 "selected" 的段落&#xff1a; $("p").not("#selected") 定義和用法 not() 從匹配元素集合中刪除元素。 語法 1 .not(selector) 參數描述selector字符串值&#xff0c;包含用于匹配元素的選擇器表達式。語法 …

linux 字符串加入中括號,Linux Shell 基礎 -- 總結幾種括號、引號的用法

1、雙引號 " "雙引號常用于包含一組字符串&#xff0c;在雙引號中&#xff0c;除了 "$"、""、" (反引號)"有特殊含義外&#xff0c;其余字符(如IFS、換行符、回車符等)沒有特殊含義。$ a3$ echo "$a"輸出結果為 3&#xff…

設計模式相關

多例模式 轉載于:https://www.cnblogs.com/our880tom/p/6392983.html

一個countDown在多線程調度下使用不當的分享

2019獨角獸企業重金招聘Python工程師標準>>> 一個countDown在多線程調度下使用不當的分享 1. 詭異的數據抖動 在一個需求開發過程中&#xff0c;由于有多角色需要獲取每個角色下的菜單&#xff1b;結果出現了單角色下拉去菜單沒問題&#xff0c;多角色情況下只有一個…

我堅持三年了!

閱讀本文大概需要5分鐘。不知不覺&#xff0c;公眾號寫作已經持續了3年了。2019年11月底&#xff0c;心血來潮寫了第一篇文章&#xff0c;更多是為了復盤過去的一些工作經歷。在前幾天&#xff0c;讀者數突破了16萬&#xff0c;雖然這個數字相比那些頭部大號而言并不多&#xf…

關于Qt模態框總匯

轉載請注明出處&#xff1a;http://www.cnblogs.com/dachen408/p/7285710.html 父窗體為QMainWindow&#xff1b; 當子窗體為&#xff1a; 1.QWidget&#xff0c;需要設置 this->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); this->setWindowModality(Qt::Win…

linux腳本打印循環次數,shell腳本編程基礎(3)——循環用法

本節索引&#xff1a;一、if、case條件判斷二、for、while及until循環三、循環控制語句continue、break、shift及select菜單四、信號捕捉trap在前面的基礎編程內容中&#xff0c;我們已經學習了shell腳本的順序執行及選擇執行&#xff0c;通過這兩種方式&#xff0c;可以幫我們…

RTSP服務器之————rtsp-server(輕量級RTSP / RTP流媒體服務器)

github&#xff1a;https://github.com/revmischa/rtsp-server 輕量級RTSP / RTP流媒體服務器

EF CORE 7 中的新功能:使用 ExecuteDelete 和 ExecuteUpdate 進行批量操作

原文鏈接&#xff1a;https://timdeschryver.dev/blog/new-in-entity-framework-7-bulk-operations-with-executedelete-and-executeupdate原文作者&#xff1a;tim_deschryver翻譯&#xff1a;沙漠盡頭的狼(谷歌翻譯加持)Entity Framework 7 包括一些已被要求的流行功能&#…

java 簡單json和對象相互轉換

2019獨角獸企業重金招聘Python工程師標準>>> package Fasterxml; import com.fasterxml.jackson.databind.ObjectMapper; import mode.User; import java.io.StringWriter; import java.util.ArrayList; import java.util.List;/*** maven...**<dependency>* …