No.22 Corticonでシフト表を自動作成する2/2
2017.11.06 Progress Corticon
本エントリーは株式会社アシスト様が寄稿したエントリー(https://www.ashisuto.co.jp/product/category/brms/progress_corticon/column/detail/brmstech22.html)を転載したものとなります。
前回のコラムでは、Corticonの宣言型・関数型プログラミング言語としての側面を活かした実装サンプルとして、シフト表を自動作成するルールを紹介しました。
しかし、前回のシフト表は簡単なサンプルのため、Corticonの手続き型・命令型プログラミング言語としての側面が強い機能は使用しませんでした。
今回のコラムでは、もう少し複雑なシフト表を作成するルールを題材にします。前回のコラムでは担当者情報だけが入力パラメータでしたが、今回のコラムのサンプルでは担当者情報だけではなく枠情報も入力パラメータになっています。このような入力パラメータの次元が増えた等の事情で、複雑な処理が必要になった場合、Corticonの手続き型・命令型言語の側面も活かしたルールを実装する必要があります。
[記事執筆環境]
Corticon 5.5.2.30, および 5.6.1.6
※Corticon 5.5.2.7では本記事の サンプルは動作しません。
担当者情報と枠情報が可変なシフト表を自動作成するルール
今回のコラムのシフト表の条件は、以下にします。
- ルールへの入力パラメータは複数の担当者情報と複数の枠情報で、個数はそれぞれ可変。
- それぞれの担当者情報には、担当することができない枠情報を複数設定可。(設定しないこともできる。)
- それぞれの枠は、固定の担当者を設定可。(固定担当者なしにすることもできる。)
- 連続した枠に、同じ担当者の連続は不可。
前回のコラムのシフト表の条件と比較すると、枠情報も入力パラメータが可変で枠の個数や条件(固定担当者)の設定ができるようになっています。
変更点はこれだけですが、語彙やルールには大きな変更が必要になり、前回と同じ要領では実装できません。
具体的にどのような語彙とルールを実装すれば良いか、以下で解説していきます。
■語彙の作成
このシフト表ルールを作成するにあたって、以下のような語彙「シフト表.ecore」を作成しました。
<シフト表.ecoreの設定表>
エンティティ名 | 説明 | |
担当者 | 入力データ。担当者情報。 | |
属性名 | 型 | |
氏名 | 文字列 | 担当者の氏名 |
関連性名 | カーディナリティ | |
不可枠 (不可枠) | 1->* | 「不可枠」エンティティとの関連性 |
エンティティ名 | 説明 | |
枠 | 入力データ。枠情報。 | |
属性名 | 型 | |
固定担当者 | 文字列 | 枠に固定の担当者氏名。指定しない場合は「なし」 |
枠番号 | 整数 | 枠のID番号。1から始まる連番 |
枠名 | 文字列 | 枠名 |
エンティティ名 | 説明 | |
シフト表 | 出力データ。木構造のシフト表を表現する。 | |
属性名 | 型 | |
最終候補フラグ | ブーリアン | シフト表候補として正しいかどうかのフラグ |
担当者氏名 | 文字列 | 枠に割り当てられた担当者の氏名 |
枠名 | 文字列 | 割り当てる枠名 |
関連性名 | カーディナリティ | |
シフト表 (シフト表) | 1->* | 「シフト表」エンティティ(自分自身)との関連性 |
エンティティ名 | 説明 | |
最終候補配列 | 出力データ。シフト表ツリーを文字列に変換。 | |
属性名 | 型 | |
担当者名配列 | 文字列 | 担当者氏名を枠順に並べたもの |
エンティティ名 | 説明 | |
カウンター | 内部処理用エンティティ。 | |
属性名 | 型 | |
i | 整数 | ループ処理計算用の拡張一時属性。 |
前回のコラム「No.21 Corticonでシフト表を自動作成する1/2」で作成した語彙の構造と比較するとかなり複雑です。
特に「シフト表」エンティティは自分自身を関連性にもつ循環型のツリー構造になっていますので、ご注意ください。
また、ルール処理内で計算用に使用する拡張一時属性「i」だけを持った「カウンター」エンティティも作成しています。
これだけでは、それぞれどのように使用されるかイメージしにくいので、記事後半の具体的な入力値・出力値と処理内容の解説もあわせて確認してください。
参考までに、Corticon Studioで作成した「シフト表.ecore」は以下です。
<Corticon Studioで表示したシフト表.ecore>
■ルールシートとルールフローの作成
以下の2つのルールシートを作成しました。
<初期化.ers>
<シフト表作成.ers>
「初期化.ers」と「シフト表.ers」の内容はほとんど同じですが、スコープやフィルタ、条件の設定が微妙に異なっていることに注意してください。
また、それぞれのルールで警告(文字が黄色の箇所)が出ています。警告の内容はCorticonの完全性チェックや曖昧性チェックなどの分析機能が無効になるというものです。ルール列の中で比較対象を固定値だけではなく「エンティティ.属性」も指定した場合にこの状態になりますが、今回の場合は無視しても良い警告なので、そのままにします。
次にルールフロー「シフト表.erf」を作成しました。内容は以下です。
<シフト表.erf>
ルールシート「シフト表作成.ers」のほうには、ループ(回転マーク)を設定していることに注意してください。
■ルールの入力値と実行結果
ルールフロー「シフト表.erf」に対するテストシートを作成しました。
入力パラメータとして、以下のように担当者情報と枠情報を作成しました。
入力パラメータは必ずしも画像と同じでないといけないわけではありません。自由にパラメータの内容を変更したり個数を増減したりすることができますが、本コラムの以下の解説はこの入力値を前提にしています。
実行すると以下のような出力結果が返ってきます。
もともとの入力パラメータのほうは実行前と変化がないので閉じた状態にしています。太字の変化があった(新規に作成された)エンティティのほうに着目してください。
出力結果のシフト表はツリー構造の探索経路木になっており、「枠5」まで到達している経路が、最初の条件にしたがった正しい組み合わせの経路になっています。
■処理内容の解説
なぜこのような結果が得られるのか、Corticonの処理の内容を解説します。
前回のコラムでは以下のようなCorticonの基本的な機能を解説しました。
- 入力された全データに対する再帰的な処理
- スコープのエイリアスとフィルタ
- 総当り評価
詳細は前回のコラムを参照してください。これら1, 2, 3の機能は、Corticonの宣言型・関数型言語としての側面が強く出ています。
今回はこれらの機能に加えて、Corticonの命令型・手続き型言語としての側面が強い機能を使用しています。以下の機能です。
- ルールフローを利用してルールとデータの処理順を指定する
- ① Corticonのルールシートでは、基本的な仕様として、Corticonが最適な順序を判断するので、ルール列の処理順の指定やデータの処理順の指定ができず、どのような順番で処理されるかは見た目では判断できません。
② ルール列の処理順に関してはある程度規則性があり、またCorticon Studioの「実行順序ダイヤグラム」機能で実際の処理順を確認することができます。しかし、その処理順を任意に変更(設定)したりすることはできません。
③ また、あるデータ集合(コレクション)の中でどのデータから処理するかというデータの処理順に関しては何の
規則性も無く、ルールを実行するたびに毎回処理順序が変わります。
④ ルールフローでは、どのルールシートから処理するか、明確に処理順番を指定することができます。この機能によって、上記②, ③の点をカバーすることができます。
⑤ 例えば、ルールシートではあるデータ集合の中でどのデータから処理するかという順番は指定できませんが、
フィルタや条件で処理対象とするデータを限定することは可能です。限定するデータを変えたルールシートを複数用意し、それらのルールシートをルールフローで順次指定すれば、データの処理順を指定することと
同義になります。 - ルールフローでのループ処理
- ① Corticonでは通常はループを指定する必要はありません。前回のコラムで紹介した「1. 入力された全データに対する再帰的な処理」の機能が標準であるためです。
② それでもあえてループ処理をさせたい場合に、ルールフローの中でルールシートにループを指定するという方法があります。
③ ルールフローでルールシートにループを指定した場合、そのルールシートの最初(スコープやフィルタ処理)から最後 (全ルール列の評価と実行)までを繰り返します。
④ 繰り返す回数はCorticonの設定によって上限が決まっています。設定項目は
「com.corticon.reactor.rulebuilder.maxloops」で、デフォルトでは100に設定されています。もし100回以上繰り返したい場合はこの値を変更してください。
⑤ ループから抜ける条件はフィルタに記述し、フィルタされて残るデータが無い状態になれば、ループを抜けます。
⑥ 上記③, ④, ⑤から、ルールシート中のアクションで特定エンティティの何かの値が増減するようにしておき、その値をフィルタの条件に指定する使用方法が一般的です。
⑦ エンティティ/関連性演算子の「sortedBy」, 「at」(※)を使用し、前述した「4-⑤」の処理対象のデータを一個に限定するという考え方と上記⑥の特定エンティティの値が増減するようにしておく考え方を組み合わせると、命令形・手続き型言語における配列処理のようなアルゴリズムの実装が可能になります。本コラム中の「シフト表作成.ers」の処理内容もこれに該当します。
- ※sortedBy はエンティティの集合を指定した属性の値によってソートする演算子で、シーケンスという特殊なオブジェクトを返します。atはシーケンスに対して何番目のデータかを指定する演算子で、その指定された番号のエンティティを返します。詳細な説明や具体的な使用方法は製品マニュアル「Rule Language Guide」を参照してください。
具体的に今回のサンプルでのデータと処理の流れを追うと、以下のイメージです。
<初期化処理>
<シフト表作成処理>
なお、「シフト表作成.ers」の処理で、必要なシフト表(探索経路木)は全て出ているので、この結果をそのままクライアント側に渡せば、見た目の整形などの後処理はクライアント側で引き継げるはずです。しかし、実際の要件ではCorticon側である程度この結果を整形する必要があるかもしれません。また、出来上がったシフト表に対してCorticonのルールでさらに何らかのスコアリングや評価を行いたい場合があるかもしれません。
今回のコラムでは解説は割愛しますが、例えば、ルールシート「シフト表作成.ers」の後に、「枠5まできている経路上のシフト表の最終候補フラグをtrueにする」、「最終候補フラグがtrueのシフト表の担当者を経路別に順番に並べた文字列(最終候補配列.担当者名配列)を作成する」といった処理を行うルールシートをフローに追加すると、以下のような出力結果になります。
<整形後の出力結果>
まとめ
いかがでしたでしょうか。
前回のシフト表のサンプルに比べてルールシートは少し難しい状態になりますが、命令型・手続き型言語としての特徴も活かした結果、柔軟な入出力とルールを作成できるようになっています。そのため、今回のシフト表サンプルをベースとして、担当者や枠にもっと多くの属性や様々な条件を追加した実用的なシフト表を作成することもできます。
もともとCorticonは宣言型・関数型言語としての側面が強いため、普通の命令型・手続き型言語の配列処理のような実装はあまり向いておらず、今回のコラムのような処理の場合は、クライアント側アプリケーションで実装したりCorticonの拡張演算子・サービスコールアウト(※)を使用することも多いです。
しかし、ルールの書き方次第では、標準的なCorticonの機能だけでも複雑なアルゴリズムの実装を行うことができます。
ご興味ございましたら、Corticon体験セミナーまでご参加頂ければ幸いです。
- ※拡張 演算子・サービスコールアウトとは、Corticonのルール中で任意のJavaプログラムを実行する機能です。詳細はコラム「No.10 Corticonの【拡張演算子】と【サービスコールアウト】を使ったルール実装のしかた」 を参照してください。
著者紹介
情報基盤技術統括部 プログレス推進部 |