OptaPlanner examples その14

Cheap time scheduling


http://docs.jboss.org/optaplanner/release/latest/optaplanner-docs/html_single/index.html#cheapTimeScheduling

遂にラスト!

タスクをマシンに割り当て、消費電力を最小化します。CloudBalance や MachineReassignment に似てます。

  • CheapTimeSolution : @PlanningSolution
  • TaskAssignment : @PlanningEntity
    • Machine machine : @PlanningVariable
    • Integer startPeriod : @PlanningVariable
    • Task task

@PlanningVariable は2つ。モデリングはシンプルなんだけど、制約の実装が意外と手強い。このサンプルにはDRLがまだ無く、CheapTimeEasyScoreCalculator と CheapTimeIncrementalScoreCalculator が実装されています。理解するにはまず CheapTimeEasyScoreCalculator を見よう。

期間(Period)単位でリソースの制約や消費電力コストを計算するので、MachinePeriodPart というクラスを導入します。

        for (Machine machine : machineList) {
            List<MachinePeriodPart> machinePeriodList = new ArrayList<MachinePeriodPart>(globalPeriodRangeTo);
            for (int period = 0; period < globalPeriodRangeTo; period++) {
                machinePeriodList.add(new MachinePeriodPart(machine, period, resourceListSize));
            }
            machinePeriodListMap.put(machine, machinePeriodList);
        }

リソースの計算は MachinePeriodPart 側でやります。

        public void addTaskAssignment(TaskAssignment taskAssignment) {
            active = true;
            Task task = taskAssignment.getTask();
            for (int i = 0; i < resourceAvailableList.size(); i++) {
                int resourceAvailable = resourceAvailableList.get(i);
                TaskRequirement taskRequirement = task.getTaskRequirementList().get(i);
                resourceAvailableList.set(i, resourceAvailable - taskRequirement.getResourceUsage());
            }
        }

「休止中は、アイドル状態にしておくか停止/起動するか、安い方を選ぶ」はこのように実装されています。

                    if (previousStatus != MachinePeriodStatus.OFF) {
                        idleCostMicros += CheapTimeCostCalculator.multiplyTwoMicros(machine.getPowerConsumptionMicros(),
                                periodPowerPrice.getPowerPriceMicros());
                        if (idleCostMicros > machine.getSpinUpDownCostMicros()) {
                            idleCostMicros = 0L;
                            previousStatus = MachinePeriodStatus.OFF;
                        } else {
                            previousStatus = MachinePeriodStatus.IDLE;
                        }
                    }

そんなに難しそうに見えない?これが CheapTimeIncrementalScoreCalculator ではエライことになります。

https://github.com/droolsjbpm/optaplanner/blob/master/optaplanner-examples/src/main/java/org/optaplanner/examples/cheaptime/solver/score/CheapTimeIncrementalScoreCalculator.java

ここでは詳細に説明しませんが、insert と retract に応じたスコアのメンテナンスがかなりハードです。

DRLで書けば少なからず楽になるはずです。さてそれは次回。。。