我使用OptaPlanner來解決什麼是有效的旅行推銷員問題與時間Windows(TSPTW)。我有一個基於OptaPlanner提供的VRPTW示例的初始解決方案。OptaPlanner-TSPTW最小化總時間
現在我試圖解決我的要求,從標準TSPTW偏離,它們是:
- 我試圖儘量減少花費,而不是移動的總距離總時間。正因爲如此,空閒時間對我不利。
- 除了標準時間訪問訪問之外,我還必須支持不遲於(NLT)訪問(即X時間後不訪問)和不早於(NET)訪問(即不訪問在X時間之前)。
我目前的解決方案總是將第一次訪問的到達時間設置爲該訪問的開始時間。這對我的要求有以下問題:
- 這可能會引入不必要的空閒時間,如果訪問是在某個時間晚些時候到達其時間窗口時可以避免的,則可以避免不必要的空閒時間。
- NLT的行爲有問題。如果我定義的開始時間設置爲Long.MIN_VALUE(表示它是無限的,而不使用空值),那麼這就是NLT訪問到達的時間(與#1相同的問題)。我嘗試通過將開始時間設置爲NLT時間來解決這個問題。這導致正好趕上NLT訪問,但超出了隨後訪問的時間窗口。
我該如何解決這個/這些問題?我懷疑解決方案將涉及ArrivalTimeUpdatingVariableListener,但我不知道該解決方案應該是什麼樣子。
如果相關,我已經粘貼了下面的當前評分規則。有一點要注意的是,「距離」實際上是旅行時間。另外,出於域名原因,我鼓勵NLT和NET到達時間接近截止時間(NLT的結束時間,NET的開始時間)。
import org.optaplanner.core.api.score.buildin.hardsoftlong.HardSoftLongScoreHolder;
global HardSoftLongScoreHolder scoreHolder;
// Hard Constraints
rule "ArrivalAfterWindowEnd"
when
Visit(arrivalTime > maxStartTime, $arrivalTime : arrivalTime, $maxStartTime : maxStartTime)
then
scoreHolder.addHardConstraintMatch(kcontext, $maxStartTime - $arrivalTime);
end
// Soft Constraints
rule "MinimizeDistanceToPreviousEvent"
when
Visit(previousRouteEvent != null, $distanceFromPreviousRouteEvent : distanceFromPreviousRouteEvent)
then
scoreHolder.addSoftConstraintMatch(kcontext, -$distanceFromPreviousRouteEvent);
end
rule "MinimizeDistanceFromLastEventToHome"
when
$visit : Visit(previousRouteEvent != null)
not Visit(previousRouteEvent == $visit)
$home : Home()
then
scoreHolder.addSoftConstraintMatch(kcontext, -$visit.getDistanceTo($home));
end
rule "MinimizeIdle"
when
Visit(scheduleType != ScheduleType.NLT, arrivalTime < minStartTime, $minStartTime : minStartTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, $arrivalTime - $minStartTime);
end
rule "PreferLatestNLT"
when
Visit(scheduleType == ScheduleType.NLT, arrivalTime < maxStartTime, $maxStartTime : maxStartTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, $arrivalTime - $maxStartTime);
end
rule "PreferEarliestNET"
when
Visit(scheduleType == ScheduleType.NET, arrivalTime > minStartTime, $minStartTime : minStartTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, $minStartTime - $arrivalTime);
end
感謝傑弗裏。我相信我已經有了這個軟約束,請參閱MinimizeIdle規則(我排除NLT以免重疊PreferLatestNLT和雙罰分)。額外的軟約束是解決方案的一部分,但它並沒有解決始終從時間窗口開始的第一次訪問,即使這會不必要地引入空閒時間。 –
將時間窗口開始放在車輛上(或車庫),然後添加一條規則:「當Customer.previousStandstill是車輛並且客戶readytime高於arrivalTime時,則......」 –