OptaPlanner examples その9

Project job scheduling


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

プロジェクトのWBSガントチャートにし、依存関係/リソースを考慮して最適な順序に並べる。あー、むかし人力でやってたなー。 MISTA 2013 challenge の課題だそうです http://allserv.kahosl.be/mista2013challenge/

  • Schedule : @PlanningSolution
  • Allocation : @PlanningEntity
    • ExecutionMode executionMode : @PlanningVariable
    • Integer delay : @PlanningVariable

またちょっと語彙が分かりにくい。Project を分割したのが Job で、その Job を何日間実行するか(duration)、をラップしたのが ExecutionMode (Modeって感じじゃないよなー)。開始までの日にち(delay)と ExecutionMode の組み合わせ(共にPlanningVariable)を保持するのが Allocation です。Allocation は他に predecessorAllocationList (先行配置リスト)、successorAllocationList(後行配置リスト)、sourceAllocation(開始配置)、sinkAllocation(終了配置)を持っています。これらは静的な条件から得られるので PlanningVariable ではないです。

今回は で新ネタがあります。

  <scoreDirectorFactory>
    <scoreDefinitionType>BENDABLE</scoreDefinitionType>
    <bendableHardLevelsSize>1</bendableHardLevelsSize>
    <bendableSoftLevelsSize>2</bendableSoftLevelsSize>
    <incrementalScoreCalculatorClass>org.optaplanner.examples.projectjobscheduling.solver.score.ProjectJobSchedulingIncrementalScoreCalculator</incrementalScoreCalculatorClass>
    <!--<scoreDrl>org/optaplanner/examples/projectjobscheduling/solver/projectJobSchedulingScoreRules.drl</scoreDrl>-->
  </scoreDirectorFactory>

BENDABLE を指定すると、Hard / Soft score をそれぞれ複数レベル(=種類)持つことができます。この場合は2レベル(=種類)の Soft score を持ち、個別にスコアを add できます。 http://docs.jboss.org/optaplanner/release/latest/optaplanner-docs/html_single/index.html#bendableScore

DRLの例:第二引数の '1' がレベルを表します。スコアの比較時は、レベルが小さい方が優先されます。つまり、HardMediumSoft の3段階よりさらに柔軟に設定できるということです。

scoreHolder.addSoftConstraintMatch(kcontext, 1, -$maxProjectEndDate.intValue());

また、今回のサンプルはデフォルトで DRL ではなく、incrementalScoreCalculatorClass を使っています。ProjectJobSchedulingIncrementalScoreCalculator を見ればよいのですが、コメントアウトされている projectJobSchedulingScoreRules.drl と見比べると。。。やっぱり DRL のほうが分かりやすいですね。ワーキングメモリ内のエンティティを変化させながらベストスコアを狙う LocalSearch の考え方が Drools にマッチしてるんだなあと思うのでした。incrementalScoreCalculatorClass では、そのステートフルな動作を自前のコードで保証しないといけない。