2015-03-02 46 views
0

我是Optaplanner的新手,我一直在考慮將VRP擴展到不同的問題空間。我正在使用6.1.0-Final。這是一個相當困難的問題,但這裏有:Optaplanner - 在使用多個計劃變量時鏈接計劃實體'腐敗'

規劃實體 - 由運輸者(即貨船)錨定的裝運(延伸停泊) 規劃變量 - 碼頭(貨物目的地),當然含蓄運輸車(作爲VRP示例中的車輛之類的影子變量)

在此路線問題中,貨物直接運輸到終端,然後返回到工廠。即運輸商服務於一個終端,然後返回到該設施。有一個不同容量/速度的運輸車隊。終端有一個位置,它定義了它與設施之間的距離。運輸公司可以服務多件貨物,但受到每次運輸的往返行程時間和「預定出發時間窗」的限制。因此,使用Transporter作爲錨點創建一個鏈條,鏈接到它所服務的所有貨件。

我幾乎複製了VRP與時間窗口的例子考慮到這個問題的領域。有影子變量稱爲previousStandstill和arrivalTime(這是到達設施而不是終端)。我修改了ArrivalTimeUpdatingVariableListener,以便計算從最後一批貨物返回工廠的往返時間。我有嚴格的限制,以確保與貨運相關的運輸公司實際上可在預定的出發時間窗口內提供,具有足夠的運力等。我還試圖根據貨運,運輸公司和候機樓的許多屬性最大化利潤。

我遇到的問題是,貨運的到達時間屬性與上次裝運(出發時間+出行時間)的計算到達時間似乎不匹配。這隻會發生在一些貨物上,而不是全部。由於在到達時間計算中依賴於終端以及運輸者,我還嘗試添加另一個名爲'previousTerminal'的影子變量,並用它來試圖確保針對貨件的上一個終端等於終端前一個標準(使用TerminalUpdatingVariableListener)。

但是,這似乎並不奏效,而且我看到Shipment實例上的'PreviousTerminal'與previousStandstill(Shipment)的終端之間不匹配。再次,這隻發生在一些貨運中。就好像終端屬性相對於以前的貨件在TerminalUpdatingVariableListener上觸發afterVariableChanged事件時得到更新。

下面是一個輸出示例。在這裏你可以看到貨物後面有'***************不匹配貨物運輸時間*******************'有一個'以前的終端',不符合鏈中上一批貨的終端。

Shipment 00001, amount 150000.0, terminal Terminal G, transporter North Sea LNG 001, previous shipment null, prev shp term Terminal J, lastShipmentTransitTime 0, thisShipmentTransitTime 5844 
Shipment 00002, amount 180000.0, terminal Terminal J, transporter North Sea LNG 004, previous shipment null, prev shp term Terminal J, lastShipmentTransitTime 0, thisShipmentTransitTime 9179 
Shipment 00003, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment null, prev shp term Terminal J, lastShipmentTransitTime 0, thisShipmentTransitTime 6656 
Shipment 00004, amount 180000.0, terminal Terminal J, transporter North Sea LNG 003, previous shipment null, prev shp term Terminal G, lastShipmentTransitTime 0, thisShipmentTransitTime 10199 
Shipment 00005, amount 150000.0, terminal Terminal J, transporter North Sea LNG 006, previous shipment null, prev shp term Terminal J, lastShipmentTransitTime 0, thisShipmentTransitTime 11474 
Shipment 00006, amount 150000.0, terminal Terminal J, transporter North Sea LNG 004, previous shipment 00002, prev shp term Terminal J, lastShipmentTransitTime 9179, thisShipmentTransitTime 9179 
Shipment 00007, amount 100000.0, terminal Terminal J, transporter North Sea LNG 001, previous shipment 00001, prev shp term Terminal G, lastShipmentTransitTime 5844, thisShipmentTransitTime 12239 
Shipment 00008, amount 250000.0, terminal Terminal G, transporter North Sea LNG 002, previous shipment 00003, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 5157 
Shipment 00009, amount 200000.0, terminal Terminal C, transporter North Sea LNG 003, previous shipment 00004, prev shp term Terminal J, lastShipmentTransitTime 10199, thisShipmentTransitTime 11001 
Shipment 00010, amount 150000.0, terminal Terminal E, transporter North Sea LNG 001, previous shipment 00007, prev shp term Terminal G, lastShipmentTransitTime 5844, thisShipmentTransitTime 15085 
***************Mismatching shipment transit times******************* 
Shipment 00011, amount 200000.0, terminal Terminal J, transporter North Sea LNG 003, previous shipment 00009, prev shp term Terminal B, lastShipmentTransitTime 6286, thisShipmentTransitTime 10199 
***************Mismatching shipment transit times******************* 
Shipment 00012, amount 100000.0, terminal Terminal J, transporter North Sea LNG 006, previous shipment 00005, prev shp term Terminal J, lastShipmentTransitTime 11474, thisShipmentTransitTime 11474 
Shipment 00013, amount 250000.0, terminal Terminal G, transporter North Sea LNG 002, previous shipment 00008, prev shp term Terminal G, lastShipmentTransitTime 5157, thisShipmentTransitTime 5157 
Shipment 00014, amount 200000.0, terminal Terminal E, transporter North Sea LNG 003, previous shipment 00011, prev shp term Terminal J, lastShipmentTransitTime 10199, thisShipmentTransitTime 12571 
Shipment 00015, amount 150000.0, terminal Terminal E, transporter North Sea LNG 006, previous shipment 00012, prev shp term Terminal J, lastShipmentTransitTime 11474, thisShipmentTransitTime 14143 
Shipment 00016, amount 150000.0, terminal Terminal J, transporter North Sea LNG 001, previous shipment 00010, prev shp term Terminal E, lastShipmentTransitTime 15085, thisShipmentTransitTime 12239 
Shipment 00017, amount 200000.0, terminal Terminal J, transporter North Sea LNG 003, previous shipment 00014, prev shp term Terminal J, lastShipmentTransitTime 10199, thisShipmentTransitTime 10199 
***************Mismatching shipment transit times******************* 

我花了相當多的時間試圖瞭解這裏發生了什麼。我試圖改變ShadowVariable資源中的順序,以及其他很多嘗試和錯誤的嘗試,但似乎沒有任何辦法可以解決這個鏈條的「腐敗」問題。

也許這是我對這個工具的無知,但是會感謝一些指導/指針,因爲到目前爲止我對它的印象都很深刻。

非常感謝任何支持,並耐心閱讀所有這一切!

更新 - 遵循'FULL_ASSERT'模式。以下異常引發,現在(沒看到這之前)...不知道這意味着什麼,但...

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Solving failed. ... Caused by: " java.lang.IllegalStateException: Score corruption: the workingScore (-2957hard/57945soft) is not the uncorruptedScore (-2957hard/57964soft) after completedAction (Shipment 00002, amount 180000.0, terminal Terminal G, transporter North Sea LNG 002, previous shipment null, prev shp term Terminal B, lastShipmentTransitTime 0, thisShipmentTransitTime 5157 => [Terminal-8]): The corrupted scoreDirector has 5 ConstraintMatch(s) which are in excess (and should not be there): org.optaplanner.examples.shipscheduling.solver/arrivalAfterLoadingWindow/level0/[Shipment 00003, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00002, prev shp term Terminal G, lastShipmentTransitTime 5157, thisShipmentTransitTime 6656]=-4456 org.optaplanner.examples.shipscheduling.solver/arrivalAfterLoadingWindow/level0/[Shipment 00008, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00003, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 6656]=-112 org.optaplanner.examples.shipscheduling.solver/maximise profit/level1/[Shipment 00013, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00008, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 6656]=4009 org.optaplanner.examples.shipscheduling.solver/maximise profit/level1/[Shipment 00008, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00003, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 6656]=10410 org.optaplanner.examples.shipscheduling.solver/terminal not big enough for transporter/level0/[[Terminal-2], [Transporter-2], Shipment 00013, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00008, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 6656]=-70000 The corrupted scoreDirector has 3 ConstraintMatch(s) which are missing: org.optaplanner.examples.shipscheduling.solver/arrivalAfterLoadingWindow/level0/[Shipment 00003, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00002, prev shp term Terminal G, lastShipmentTransitTime 5157, thisShipmentTransitTime 6656]=-2957 org.optaplanner.examples.shipscheduling.solver/maximise profit/level1/[Shipment 00008, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00003, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 6656]=10398 org.optaplanner.examples.shipscheduling.solver/maximise profit/level1/[Shipment 00013, amount 250000.0, terminal Terminal B, transporter North Sea LNG 002, previous shipment 00008, prev shp term Terminal B, lastShipmentTransitTime 6656, thisShipmentTransitTime 6656]=10316 Check your score constraints....

更新 - 更新Optaplanner核心6.2.0.CR4和有與啓用「FULL_ASSERT」的另一個例外情況。如果我禁用到達時間規則檢查,那麼我不會再看到任何例外......但我很難理解爲什麼會這樣。是否有關於我需要了解的「撤消移動」的具體內容?

Caused by: java.lang.IllegalStateException: The moveClass (class org.optaplanner.core.impl.heuristic.move.CompositeMove)'s move ([Shipment 00009, amount 200000.0, assigned terminal null, maxTerminalCapacity null, and transporter null, capacity null, profit 0, periodStart 18000, periodEnd 18200, arrival time18000, departure time = 18000, return time 18000, lastShipmentTransitTime 0, thisShipmentTransitTime 0, previous shipment null => [Transporter-2], Shipment 00009, amount 200000.0, assigned terminal null, maxTerminalCapacity null, and transporter null, capacity null, profit 0, periodStart 18000, periodEnd 18200, arrival time18000, departure time = 18000, return time 18000, lastShipmentTransitTime 0, thisShipmentTransitTime 0, previous shipment null => [Terminal-2]]) probably has a corrupted undoMove ([Shipment 00009, amount 200000.0, assigned terminal null, maxTerminalCapacity null, and transporter null, capacity null, profit 0, periodStart 18000, periodEnd 18200, arrival time18000, departure time = 18000, return time 18000, lastShipmentTransitTime 0, thisShipmentTransitTime 0, previous shipment null => null, Shipment 00009, amount 200000.0, assigned terminal null, maxTerminalCapacity null, and transporter null, capacity null, profit 0, periodStart 18000, periodEnd 18200, arrival time18000, departure time = 18000, return time 18000, lastShipmentTransitTime 0, thisShipmentTransitTime 0, previous shipment null => null]). Or maybe there are corrupted score rules. Check the Move.createUndoMove(...) method of that Move class and enable EnvironmentMode FULL_ASSERT to fail-faster on corrupted score rules. Score corruption: the lastCompletedStepScore (-6256hard/0soft) is not the undoScore (-19256hard/0soft).

UPDATE - 修復

好了很多周圍挖後,我發現,去除:

&& ObjectUtils.notEqual(shadowShipment.getArrivalTime(), arrivalTime) 

while (shadowShipment != null) && ObjectUtils.notEqual(shadowShipment.getArrivalTime(), arrivalTime)) { 

的ArrivalTimeUpdatingVariableListener內似乎解決問題,雖然我不是完全肯定爲什麼呢......我猜這會讓它放慢一點。

+0

是否開啓enviromnentMode FULL_ASSERT使其失敗遲早? – 2015-03-02 10:54:09

+0

嗨 - 我現在看到一個異常提出,這是之前沒有... ScoreCorruption – Justin 2015-03-02 11:03:48

+0

這意味着它失敗的時間越早,越接近腐敗第一次創建時。打開TRACE日誌記錄。看看那個分數腐敗例外中描述的舉動。當移動發生錯誤時,查看是否可以調試變量偵聽器。 – 2015-03-02 12:46:53

回答

0

感謝指針傑弗裏。

該問題與while循環中斷有關,一旦它發現到貨時間沒有改變的貨件。必須在某些情況下,'shadowShipment'的到貨時間相同,但不適用於連鎖店的後續裝運。

我已經更新了 'ArrivalTimeUpdatingListener' 如下(這工作正常):

protected void updateArrivalTime(ScoreDirector scoreDirector, Shipment sourceShipment) { //first get the previous shipment and the departure time. If the the previousStandstill is a transporter //then the departure time will be null Standstill previousStandstill = sourceShipment.getPreviousStandstill(); Integer departureTime = (previousStandstill instanceof Shipment) ? ((Shipment) previousStandstill).getDepartureTime() : null; Shipment shadowShipment = sourceShipment; //calculate the arrival time of the source shipment based on the departure time of the last Integer arrivalTime = calculateArrivalTime(shadowShipment, departureTime); //loop through each shipment in the chain from the source shipment forwards while (shadowShipment != null) { //only update the arrival time if it has changed if(ObjectUtils.notEqual(shadowShipment.getArrivalTime(), arrivalTime)) { scoreDirector.beforeVariableChanged(shadowShipment, "arrivalTime"); shadowShipment.setArrivalTime(arrivalTime); scoreDirector.afterVariableChanged(shadowShipment, "arrivalTime"); } //set the variables for the next loop departureTime = shadowShipment.getDepartureTime(); shadowShipment = shadowShipment.getNextShipment(); arrivalTime = calculateArrivalTime(shadowShipment, departureTime); } }