Progress Corticon
【Corticon Tech コラム】
No.13 ルールシートのプロセッシングモード (2017年3月24日)
|
2016年4月からProgress製品を担当しています棚橋浩志です。弊社では年度初めにその年の目標として漢字一文字を発表します。私は『脱』を発表して、脱・手続き型プログラミング言語、脱・オブジェクト指向型プログラミング言語を目標に Corticon に取り組んで行きたいと思います。
さて今回はルールシートでのプロセッシングモードについて記事にしてみます。
バブルソート
アルゴリズムの代名詞でもあるバブルソートですが、代名詞という冠が付くだけに私も社内で javascript の新人教育で使っています。構成する要素のインデックスを隣同士で比較して、条件に適合すれば入れ替えるという処理になります。
では反復処理演算子 for を使用してプログラムを作成しましょう。 ここでは10個の数字配列(要素)を昇順にソートする仕様でjavascript のプログラムを作成してみましょう。
var warray = new Array( 100 , 90 , 80 , 70 , 60 , 50 , 40 , 30 , 20 , 10 ); for (var wcnt02= 0 ; wcnt02 < warray.length - 1 ; wcnt02++) { if(warray[wcnt02] > warray[wcnt02 + 1]) { var wint = warray[wcnt02]; warray[wcnt02] = warray[wcnt02 + 1]; warray[wcnt02 + 1] = wint; } }
注意点は
1) 比較回数は、要素数 - 1 になる点warray.length - 1
2) 値は一時領域に待避して入れ替えをする点var wint = warray[wcnt02]
3) この反復処理1回で最大値が配列最後の要素 warray[warray.length]に移動される点
になります。
3)は次のステップに重要な事象で、1回の反復処理では最大値が配列最後の要素に1つ決まるだけなので、この反復処理をさらに反復処理させる必要があります。
そしてこの反復処理させる回数は、1回反復処理が行われると1つ最大値(最小値)が決定されるため、1回ずつ減らして行く必要があることです。これを実装するとつぎのようになります。
var warray = new Array( 100 , 90 , 80 , 70 , 60 , 50 , 40 , 30 , 20 , 10 ); for (var wcnt01= 0 ; wcnt01 < warray.length - 1 ; wcnt01++) { for (var wcnt02= 0 ; wcnt02 < warray.length - wcnt01 - 1 ; wcnt02++) { if(warray[wcnt02] > warray[wcnt02 + 1]) { var wint = warray[wcnt02]; warray[wcnt02] = warray[wcnt02 + 1]; warray[wcnt02 + 1] = wint; } } }
Corticonでのバブルソート (手続き型プログラミング風)
Corticonでこのバブルソートを実装して見ましょう。
ところで javascript の新人教育ではこのバブルソートはプログラミング技法を学ぶことが主旨なのですが、毎回この主旨を無視したある意味勉強熱心な生徒がいます。それはArrayオブジェクトのsortメソッドを使って課題を10分程度で仕上げて、さらには「作りましたが動きません!」と質問に来ます。・・・今回もまたか・・・と思います。
(Arrayオブジェクトのsortメソッドは文字列のソートに特化したメソッドなので、数字をソートする場合にはもうひとひねり必要です)
手続き型プログラミング編という題目に沿えば、上のjavascriptスクリプト・コードをCorticonのルールシートで実装することが望ましいのですが、Corticon でも sortedBy演算子があるのでこちらを使用したルールを作成してみましょう。
語彙:proceduralSort.ecore
|
まず入出力の定義を語彙ファイルで作成します。 10個の要素をソートすると仮定して、sortエンティティに int01属性 から int10属性 まで整数型で作成しました。
そして要素10個を並び替える作業領域を作成してソートするための語彙を追加します。実装方法はいろいろあると思いますが、作業領域が動的に作成できて、sortedBy演算子を使用できるようにつぎのように作成しました。
語彙:proceduralSort.ecore
|
つぎにルールシートを作成します。語彙ファイルと同様に実装方法はいろいろあると思いますがつぎのように作成してみました。
ルールシート:init.ers
init.ers
ではまず要素を格納する器を作成します。
|
アクションA行でwork.integer01 = 0と初期化して、アドバンス推論自己トリガ(上図の赤枠)を使用して、アクションC行でtemp.index = work.integer01 および temp.ranking=-1 の値を持つ10個の器を作成します。
このようにアドバンス推論自己トリガは、「手続き型プログラミング」の概念でいうところのカウンターで数字をインクリメントさせてループさせたい場合に使用します。ルールシートではアクションE行でカウンターを設定しています。
今一度 JavaScript のプログラム・コードを参照ください。
for (var wcnt01= 0 ; wcnt01 < warray.length - 1 ; wcnt01++)
で定義されているスクリプトと同じ動きをします。「手続き型プログラミング」をしてきた人には非常にわかりやすいプロセッシングモードだと思います。
ルールシート:init2.ers
器を作成したら、その器に要素を入れる
init2.ers
を作成します。
|
条件a行のtemp.indexの値を条件にして、アクションA行のtemp.valueに各列の値を代入します。続いてプロセッシングモードをアドバンス推論に設定しました。
init.ers
のようにアドバンス推論自己トリガに設定して、カウンターを設定しても同じ動作をしますが、 temp.valueの値は必ず取得されたデータで更新されるという前提があるためにプロセッシングモードをアドバンス推論にしました。反対にtemp.valueの値が更新されないことがある場合には、プロセッシングモードをアドバンス推論自己トリガに設定してカウンターを組み込む必要があります。何故ならアドバンス推論は『データの状態に変化がないと、ループ反復は止まります。』 (Corticon Studio:ルール モデリング ガイド P156参照)という仕様のため、ループの課程で1回でもデータを更新しないことがある場合にはループ処理を中断するからです。
ルールシート:sort_init.ers
これまでの2つのルールシートでソートを実行する準備が整いましたので、ソートの処理をルールシートに作成します。
まずはsortedBy -> firstを使用するために
sort_init.ers
でカウンターを初期化します。
|
ルールシート:sort.ers
つぎにアクションA行でカウンターを使用して sortedBy -> first で順位を決定します。この部分も実装方法はいろいろあると思いますが、以下
sort.ers
を作成しました。
|
init.ers
でtemp.rankingを-1に初期化しているのでArray.rankingの値が0未満とフィルタで設定して、Array -> sortedBy(value) -> first.ranking = work.integer01を実行します。 このArray -> sortedBy(value) -> first.ranking は
sort.ers
で初回しか実行されません。そのためこのルールに アドバンス推論や アドバンス推論自己トリガを設定しても、同じ値を保持します。そのためにルールフローで、この
sort.ers
にループ設定をして、ループの都度 Array -> sortedBy(value) -> first.ranking が実行されるようにします。ソート処理はこの
sort_init.ers
と
sort.ers
2つのルールシートで完結します。
ルールシート:init2.ers
最後に入出力用の語彙に、ソートした結果を戻すルールシート
sort_end.ers
を作成します。
|
この処理はちょうど
init2.ers
の逆の処理になります。ループが反復されても必ずどこかの値を変化させるという前提でプロセッシングモードをアドバンス推論に設定します。
ルールフロー:proceduralSort.erf
以下ルールフローを作成します。
|
注意点は 先に説明した
sort.ers
にループの設定をします。
テストシート:proceduralSort.ert
バブルソートのルールが完成したのでテストを行ってみましょう。
|
問題なくソートが実行されましたが、膨大なルールの集大成になってしまいました。Corticonには先頭データを操作するまたは最後のデータを操作する演算子はありますが、中程のデータに対して順列を保持して操作するといった演算子はありません。
JavaScriptのソースで言えば、外側のfor文は制御できるが、入れ子になっている内側のfor文の処理は苦手ということになります。
一方でバブルソートに付きまとう無駄な処理がこのワークフローにも含まれています。
例えば JavaScript で定義すれば
という要素の場合には最後の2つの要素を1回交換するだけで済みますが、比較処理は実に46回行われます。言い換えれば『46回比較処理をした結果10個の要素がソートされます』という話になり、要素交換が主たる処理なのか要素比較が主たる処理なのかわからなくなります。 これが手続き型プログラミングの長所でもあり短所でもあります。
そこで脱・手続き型プログラミングということでCorticonならではの実装をしてみましょう。
Corticonでのバブルソート (Corticon風)
Corticonでのバブルソート (手続き型プログラミング風)で、プロセッシングモードの アドバンス推論とアドバンス推論自己推論の違いは理解頂けたでしょうか。
アドバンス推論は『データの状態に変化がないと反復が強制停止する』モードであり、 アドバンス推論自己推論は『カウンターを使用して、データの状態に変化がなくても反復を強制停止させない』モードとなります。
(アドバンス推論自己トリガにカウンターが記述されていない場合には、アドバンス推論として動きます)
このCorticonの特性を利用すると実は簡単にバブルソートがつくれてしまいます。もうおわかりになりましたか?バブルソートの根本的な処理は『要素を比較して交換する』ということです。交換処理がなくなったら処理は終了です。(=『データの状態に変化がないと反復が強制停止する』)。46回比較する必要はないのです。早速実装してみましょう。
語彙:sort.ecore
まずは語彙ファイルを作成します。手続き型プログラミング風同様に入出力の定義をします。
|
語彙ファイルは以上です。驚かれるかもしれませんがソートのための項目追加はtemp属性だけです。
ルールシート:sort.ers
つぎにルールシートを作成します。
|
『左右の要素を比較して左の値が大きければ交換する』ということを記載しただけです。なお値の交換には値を sort.temp に一時待避させて移動します。これはプログラミングの鉄則です。そしてこのルールシートにアドバンス推論を設定して完成です。データの状態に変化がなくなったらCorticonは反復処理を強制停止します。またルールシートが1つなのでルールフローで制御する必要もありません。
テストシート:sort.ert
ではテストを実施してみましょう。
|
問題なくソートが実行されました。手続き型プログラミング風はここまで簡単にはなりません。
最後に
実は手続き型プログラミング風のルールの作成にはまたしても3日以上費やしました。振り返れば思うように動かないことに時間をとられ調査して、課程で別の問題に突き当たりと、開発さながらの状況になりました。一方Corticon風のルールはテストの実施まで1時間でした。今回の結果には驚きを隠せなかったと同時に、前回も指摘した脱・手続き型プログラミングの思考回路でルールを作成する必要があると実感しました。 その結果開発工数も大幅に削減され Corticon をちょっぴり見直しました。
皆様も是非『脱・手続き型プログラミング』思考で Corticonをご活用下さい。
「Corticon Tech コラム」記事一覧
- 2022.11.16アシスト、DXに欠かせないルールべースAI「Progress Corticon」の新バージョン6.3を提供開始
- 2022.4.7アシストがProgress社製品の販売活動において「Progress Accelerate Partner Distributor」を受賞
- 2022.2.16生命保険エコシステム リリース第2弾 「生命保険給付金支払いプラットフォーム」採用2社目
- 2021.11.17生命保険エコシステム リリース第1弾 「生命保険給付金支払いプラットフォーム」始動
- 2021.9.6アシスト、「GOLD Cloud Platformコンピテンシー」取得で、Microsoft Azure上での業務自動化を強力に支援