2014年2月28日金曜日

Drools - ベイジアンネットワーク インテグレーション

原文: Drools - Bayesian Belief Network Integration by Mark Proctor (Drools & jBPM)

プラグイン機構の信念システム(pluggable belief system)の開発は次のステージへと進んでいます。現在、ベイジアンネットワークサブシステムとのインテグレーションに取り組んでいます。何がおこっているのかしっかりと理解したかったので、私は独自実装を進めています。

私はこの素晴らしいチュートリアルを実践しています:
http://www.mathcs.emory.edu/~whalen/Papers/BNs/Intros/BayesianNetworksTutorial.pdf

このチュートリアルも実践しています:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.135.7921&rep=rep1&type=pdf

与えられたグラフから最適なジャンクションツリー(junction trees)を生成する非常に効率的なアルゴリズムができました。最終的なジャンクションツリーを生成する前に、まず moralise し triangulate します。ジャンクションツリーアルゴリズムはグラフをツリーに変換します。よって、実行時に発生するネットワークの伝播は NP困難(NP-hard)ではなくなりました。

全ての小さな作業パーツに対して、ローレベルなユニットテストをたくさん書きました。しっかりとした物を作れていることを確認したかったですし、最終的な変換結果を単純にテストするだけでは充分ではないからです。どのようなものかアイディアをつかむ為、前述した2つのチュートリアルにある例を対象としたユニットテストを作りました。注意点としては効率化する為、クリークをエンコードするのにビットセットを使っています。最初のmainベイジアンネットワークのみグラフオブジェクトとして表記されています。その後、 隣接行列(adjacency matrix)によりすべて変換されます。-軽量性と高速性は維持されます。

オラシオ(Horacio)はベイジアンネットワークのUIに取り組んできました。まだ初期段階ですが、ベイジアン XML BIF標準を解析し、ノードを表示することができます。次に彼がコネクターを追加した後、私達は編集機能の実装に取り組む予定です。動画をご覧いただけます:
http://vimeo.com/85732009

次に、私はメッセージの伝播(message propagation)に取り組む予定です。完全にインテグレートされて利用可能なプラグイン機構の信念システムを 4~6週間後にご提供できればと思います。進捗状況はブログでお伝えします。

例1
@Test
public void testFullExample1() {
    // from "Bayesian Belief Network Propagation Engine In Java"
    // the result here is slightly different, due to ordering, but it's still correct.
    // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.135.7921&rep=rep1&type=pdf
    Graph<BayesVariable> graph = new GraphImpl<BayesVariable>();
    Vertex xa = addVertex( graph );
    Vertex xb = addVertex( graph );
    Vertex xc = addVertex( graph );
    Vertex xd = addVertex( graph );
    Vertex xe = addVertex( graph );
    Vertex xf = addVertex( graph );
    Vertex xg = addVertex( graph );
    Vertex xh = addVertex( graph );

    connectParentToChildren(xa, xb, xc);
    connectParentToChildren(xb, xd);
    connectParentToChildren(xc, xe, xg);
    connectParentToChildren(xd, xf);
    connectParentToChildren(xe, xf, xh);
    connectParentToChildren(xg, xh);


    BitSet clique1 = bitSet("00000111"); // a, b, c
    BitSet clique2 = bitSet("00001110"); // b, c, d
    BitSet clique3 = bitSet("00011100"); // c, d, e
    BitSet clique4 = bitSet("01010100"); // c, e, g
    BitSet clique5 = bitSet("11010000"); // e, g, h
    BitSet clique6 = bitSet("00111000"); // d, e, f


    BitSet clique1And2 = bitSet("00000110"); // b, c
    BitSet clique2And3 = bitSet("00001100"); // c, d
    BitSet clique3And4 = bitSet("00010100"); // c, e
    BitSet clique4And5 = bitSet("01010000"); // e, g
    BitSet clique3And6 = bitSet("00011000"); // d, e

    // clique1
    JunctionTreeBuilder jtBuilder = new JunctionTreeBuilder( graph );
    JunctionTreeNode<BayesVariable> root = jtBuilder.build();
    assertEquals( clique1, root.getBitSet() );


    // clique2
    assertEquals(1, root.getSeparators().size());
    JunctionTreeSeparator sep =  root.getSeparators().get(0);
    assertEquals( clique1And2, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode2 =sep.getNode2();
    assertEquals( clique1, sep.getNode1().getBitSet() );
    assertEquals( clique2, jtNode2.getBitSet() );
    assertEquals(2, jtNode2.getSeparators().size());

    // clique3
    assertSame( sep, jtNode2.getSeparators().get(0));
    sep =  jtNode2.getSeparators().get(1);
    assertEquals( clique2And3, sep.getBitSet() );
    JunctionTreeNode<BayesVariable>  jtNode3 =sep.getNode2();
    assertEquals( clique2, sep.getNode1().getBitSet() );
    assertEquals( clique3, jtNode3.getBitSet() );
    assertEquals( 3, jtNode3.getSeparators().size());

    // clique4
    assertSame( sep, jtNode3.getSeparators().get(0));
    sep =  jtNode3.getSeparators().get(1);
    assertEquals( clique3And4, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode4 = sep.getNode1();
    assertEquals( clique3, sep.getNode2().getBitSet() );
    assertEquals( clique4, jtNode4.getBitSet() );
    assertEquals( 2, jtNode4.getSeparators().size());

    // clique5
    assertSame( sep, jtNode4.getSeparators().get(0));
    sep =  jtNode4.getSeparators().get(1);
    assertEquals( clique4And5, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode5 = sep.getNode1();
    assertEquals( clique4, sep.getNode2().getBitSet() );
    assertEquals( clique5, jtNode5.getBitSet() );
    assertEquals( 1, jtNode5.getSeparators().size());

    //clique 6
    sep =  jtNode3.getSeparators().get(2);
    assertEquals( clique3And6, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode6 = sep.getNode1();
    assertEquals( clique3, sep.getNode2().getBitSet() );
    assertEquals( clique6, jtNode6.getBitSet() );
    assertEquals( 1, jtNode6.getSeparators().size());
}


例2
@Test
public void testFullExample2() {
    // Bayesian Networks -  A Self-contained introduction with implementation remarks
    // http://www.mathcs.emory.edu/~whalen/Papers/BNs/Intros/BayesianNetworksTutorial.pdf
    Graph<BayesVariable> graph = new GraphImpl<BayesVariable>();
    Vertex xElectricity = addVertex( graph );   // 0
    Vertex xTelecom = addVertex( graph );       // 1
    Vertex xRail = addVertex( graph );          // 2
    Vertex xAirTravel = addVertex( graph );     // 3
    Vertex xTransportation = addVertex( graph );// 4
    Vertex xUtilities = addVertex( graph );     // 5
    Vertex xUSBanks = addVertex( graph );       // 6
    Vertex xUSStocks = addVertex( graph );      // 7

    connectParentToChildren( xElectricity, xRail, xAirTravel, xUtilities, xTelecom );
    connectParentToChildren( xTelecom, xUtilities, xUSBanks );
    connectParentToChildren( xRail, xTransportation );
    connectParentToChildren( xAirTravel, xTransportation );
    connectParentToChildren( xUtilities, xUSStocks );
    connectParentToChildren( xUSBanks, xUSStocks );
    connectParentToChildren( xTransportation, xUSStocks );


    BitSet clique1 = bitSet("11110000"); // Utilities, Transportation, USBanks, UStocks
    BitSet clique2 = bitSet("01110001"); // Electricity, Transportation, Utilities, USBanks
    BitSet clique3 = bitSet("01100011"); // Electricity, Telecom, Utilities, USBanks
    BitSet clique4 = bitSet("00011101"); // Electricity, Rail, AirTravel, Transportation

    BitSet clique1And2 = bitSet("01110000"); // Utilities, Transportation, USBanks
    BitSet clique2And3 = bitSet("01100001"); // Electricity, Utilities, USBanks
    BitSet clique2And4 = bitSet("00010001"); // Electricity, Transportation


    xElectricity.setContent(new BayesVariable("Electricity", xElectricity.getId(),
                                              new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.6, 0.3, 0.099}}));

    xTelecom.setContent(new BayesVariable("Telecom", xTelecom.getId(),
                                          new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.544, 0.304, 0.151}}));

    xRail.setContent(new BayesVariable("Rail", xRail.getId(),
                                       new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.579, 0.230, 0.190}}));

    xAirTravel.setContent(new BayesVariable("AirTravel", xAirTravel.getId(),
                                            new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.449, 0.330, 0.219}}));

    xTransportation.setContent(new BayesVariable("Transportation", xTransportation.getId(),
                                                 new Object[]{"Working", "Moderate", "Severe", "Failure"}, new double[][]{{0.658, 0.167, 0.097, 0.077}}));

    xUtilities.setContent(new BayesVariable("Utilities", xUtilities.getId(),
                                             new Object[]{"Working", "Moderate", "Severe", "Failure"}, new double[][]{{0.541, 0.272, 0.097, 0.088}}));

    xUSBanks.setContent(new BayesVariable("USBanks", xUSBanks.getId(),
                                          new Object[]{"Working", "Reduced", "NotWorking"}, new double[][]{{0.488, 0.370, 0.141}}));

    xUSStocks.setContent(new BayesVariable("USStocks", xUSStocks.getId(),
                                          new Object[]{"Up", "Down", "Crash"}, new double[][]{{0.433, 0.386, 0.179}}));

    JunctionTreeBuilder jtBuilder = new JunctionTreeBuilder( graph );
    JunctionTreeNode<BayesVariable> root = jtBuilder.build();


    // clique1
    assertEquals( clique1, root.getBitSet() );
    assertEquals( 1, root.getSeparators().size() );

    // clique2
    JunctionTreeSeparator sep =  root.getSeparators().get(0);
    assertEquals( clique1And2, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode2 = sep.getNode2();
    assertEquals( clique1, sep.getNode1().getBitSet() );
    assertEquals( clique2, jtNode2.getBitSet() );
    assertEquals(3, jtNode2.getSeparators().size());

    // clique3
    assertSame( sep, jtNode2.getSeparators().get(0) );
    sep =  jtNode2.getSeparators().get(1);
    assertEquals( clique2And3, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode3 = sep.getNode1();
    assertEquals( clique2, sep.getNode2().getBitSet() );
    assertEquals( clique3, jtNode3.getBitSet() );
    assertEquals(1, jtNode3.getSeparators().size());

    // clique4
    sep =  jtNode2.getSeparators().get(2);
    assertEquals( clique2And4, sep.getBitSet() );
    JunctionTreeNode<BayesVariable> jtNode4 = sep.getNode1();
    assertEquals( clique2, sep.getNode2().getBitSet() );
    assertEquals( clique4, jtNode4.getBitSet() );
    assertEquals(1, jtNode4.getSeparators().size());
}

原文: Drools - Bayesian Belief Network Integration by Mark Proctor (Drools & jBPM)

2014年2月24日月曜日

JBoss BRMS トレーニングのお試し webinar - Decision Tables

原文: JBoss BRMS Taste of Training Webinar - Decision Tables by Eric D. Schabell

Red Hat の Taste of Training webinars(トレーニングのお試し webinar)について聞いたことはありますか?

2014年3月27日に、Red Hat JBoss BPM Suite を使い decision tables(意思決定表) に焦点をあてた素晴らしいルールの基礎に関する webinar を開催します。2つのセッションに分けて行う予定です。

セッション1:
日付:         2014年3月27日
開始時間: 22:00(日本時間) // 13:00 UTC
所要時間: 60分

セッション2:
日付:         2014年3月28日
開始時間: 03:00(日本時間)// 2014/3/27 18:00 UTC
所要時間: 60分

Red Hat が提供するトレーニングの受講を検討されている方や、新しいことを学ことに積極的な方は、この企画が 受賞歴のある Red Hat® トレーニングを知る良い機会となるはずです。

個々の webinar は、Red Hat カリキュラムチームのメンバーにより提供されます。実戦的な知識や実社会の具体例が提供されます。

公演後は、必要に応じて録画をご確認ください。

Decision table(意思決定表) としてビジネスルールを定義する

迅速に更新可能なビジネスルールを作成するにあたり、ビジネスアナリストと開発者にはロール(役割)があります。ビジネスアナリストがルールを考案し、開発者がそれを実装します。作業の実現方法として、開発者が実装に使うことができる decision table(意思決定表)を利用し、ビジネスアナリストがルールを考案することができます。

ルールベースのアプリケーション用にルールを書く

ビジネスアナリストがdecision table(意思決定表)にルールを考案する為、どのようにエクセルシートを使用するかを学習します。開発者は、ビジネスルールを実装する際にエクセルシートを利用できます。

Red Hat® JBoss® BRMS を使い、私達は以下の作業方法をご紹介します:

  • エクセルシートベースのdecision table(意識決定表)を設計する
  • 実際に、エクセルシートを使い decision table(意思決定表)を作成する
  • JUnit を使い、decision table(意思決定表)をルールベースのアプリケーションに含める

Webinar への登録はこちらから

原文: JBoss BRMS Taste of Training Webinar - Decision Tables by Eric D. Schabell

2014年2月23日日曜日

PHREAK/ReteOO を学ぶ前準備

数日前から R.I.P. RETE time to get PHREAKY の翻訳に着手しましたが難航しています。Reteアルゴリズムに関する学術的なバックグラウンドが足りない為、改善ポイントが書かれていても、「ふーん、なんか良いことなんだ」ぐらいにしか思えなかったり、難解で夕日に向かって黄昏ていたりします。

 以前翻訳した、「PHREAKアルゴリズムを使った Drools 6 のパフォーマンス」や「ルールエンジンのアルゴリズムはどっちが速い? ReteOO ? Phreak?」によりアルゴリズムへの興味が沸いてきたので、本格的に基礎から勉強する決意をしました。基礎知識がつけば、より PHREAK を理解でき、さらには Drools を今まで以上に楽しめるはず。

この投稿では、勉強に使った資料を列挙します。勉強の進捗にあわせて記事は改修していきます。お薦めの資料があれば、ぜひ教えてください。

学習プラン

1:  人工知能教科書 amazonへのリンク
Drools は人工知能に関する技術が使われていると聞いたことはあったのですが、人工知能がどういった分野なのか把握していなかったので、イマイチすっきりしませんでした。

人工知能とカテゴライズされる個々の研究分野と、それぞれの関係性が歴史を振り返りながら説明されているので、人工知能と言われる分野に対してとてもクリアーになりました。

自分は Drools Expert、Drools Fusion、Optaplanner に興味があるので、Knowledge Representation、Expert System、Planning といった研究分野にフォーカスすれば良いようです。

2: 知識システムの実装基礎 amazon へのリンク
forward chaining と backward chaining の解説がとても解りやすかったので購入してみました。

今回は「知識表現と推論技術」(4章、5章、6章)を読んだのですが、例がシンプルすぎてちょっと物足りなかったです。アルゴリズムの基礎を勉強するという点では満足しています。




3: Artificial Intelligence: A Modern Approach amazon へのリンク
Droolsコミュニティーサイトのドキュメントを読んでいたら、Recommended Readingと題した章がありました。そこで、「KPR や Expert System の理論的背景を深く学びたい人にはとってもお薦め」と書かれていたので購入しました。

1152ページもあるので、どう読み進めるか検討中です。







とりあえず上記資料を読み終えた後、次のステップを考えます。翻訳作業は平行して進めます。

knowledge representation、expert system、planning に関する読書会や勉強会を企画されている方がいらしたら、ぜひお知らせください。参加希望です!

2014年2月20日木曜日

JBoss BPM Suite Webinar スライド公開 - ビジネスルール、イベント、プロセス なんてこった

原文: JBoss Webinar Slides Available - Business rules, events, and processes. Oh my! by Eric D. Schabell

以前お伝えした通り、今日 Webinar をホストしました。JBoss BPM Suite を使いあなたの会社にあるビジネスルール、イベント、プロセスを活用する為、ライブでは複数コンポーネントを解説しました。

このイベントには 約500名が登録され、イベントの最中にはたくさんのご質問をいただきました。すべての質問にお答えすることはできませんでしたが、ご心配なさらないでください。ライブ中にお答えできなかった質問に間しては来週確認し、ご質問された方々へ個別にご返答する予定でおります。

こちらが利用したスライドになります。セッションに参加できなかった方は、webinarに登録していただくことで、動画をご覧いただけます。



ご質問くださった方々は、返信をご確認ください。また、参加してくださった皆様に感謝致します。ありがとうございました。

原文: JBoss Webinar Slides Available - Business rules, events, and processes. Oh my! by Eric D. Schabell

2014年2月17日月曜日

JBoss BPM Suite Webinar - ビジネスルール、イベント、プロセス なんてこった

原文: JBoss BPM Suite Webinar - Business rules, events, and processes. Oh, my! by Eric D. Schabell

私は BPM Suite 6 をベースにし、ルールとビジネスプロセスのインテグレーションについて webinar をホストします。日程は、日本時間の 2014年2月21日 1:00AM 開始です。(February 20th, 2014 at 16:00 UTC)

こちらの概要をご確認いただければ、Webinar でカバーされる範囲を把握できます。

Webinar への登録はこちらから


JBoss BPM Suite Webinar - ビジネスルール、イベント、プロセス、なんてこった
ビジネスプロセスをコントロールする為、ビジネスルールやイベントは存在します。よって、昨今のダイナミックなビジネス環境において、迅速かつ効率的にビジネスルールを更新することは必要不可欠です。実現する為には、Business Process Management (BPM) とルール駆動型アプリケーションが鍵になります。Red Hat® JBoss® BPM Suite はこれらを助けることが可能です。

Business Process Management(BPM) の世界に飛び込む準備はできていますか?ソースコードの変更を要求しプログラマーを煩わせることなく、ビジネスユーザーはそれぞれビジネスルールを更新することができる世界です。この世界にご興味があれば、今回の Webinar をお楽しみいただけるはずです。

ビジネスプロセスとルール駆動型アプリケーションの為にある JBoss BRMS

Webinar に参加していただいた後、あなたは以下の内容が実現可能になります


  • ルール駆動型アプリケーション用のビジネスプロセスを構築する為の機能、コンポーネント、基礎概念を認識します
  • 現実世界に基づいたプロジェクトを 2つ振り返り、あなたにもお試しいただけるよう順序だてて説明します。プロジェクトを通して上記概念を現実世界に結び付けることができるようになります
  • 勤め先企業のビジネスロジックを把握し、ビジネスプロセスをデザインし始め、あなたの新しい能力により雇用主や同僚を魅了します


Webinar でお会いしましょう。その前に、まずは登録作業が必要になります ;)

原文: JBoss BPM Suite Webinar - Business rules, events, and processes. Oh, my! by Eric D. Schabell

2014年2月14日金曜日

Red Hat JBoss BPM Suite - ランタイム セッション ストラテジーの変更方法

原文: Red Hat JBoss BPM Suite - how to change runtime session strategy by Eric D. Schabell

今回の JBoss BPM Suite のヒント/トリック集では、BPMプロジェクトをデプロイする際、どうやってセッションストラテジーを設定するかご紹介します。

GitHubで公開しているデモコレクションでご確認いただけますが、シンプルなデモプロジェクトを使います。JBoss BPM Suite でお試しいただけます。

JBoss BPM Suite のインストール作業は別途実施していただく必要があります。JBoss BPM Suite インストールプロジェクトをご利用いただくことで、遭遇する可能性のあるトラブルを回避できます。

ゴール

前回の投稿で、ルールからプロセス変数にアクセスする方法をご紹介しました。セッション ストラテジーの初期値に付随する問題と、プロセスインスタンスがスタートする度にルールが実行される解決法をご理解いただけたかと思います。

今回は、ランタイム セッション ストラテジーの変更方法をご紹介します。これにより、前回のような特別な修正をルールに実施する必要はありません。プロセスインスタンスがスタートする度にルールは実行されます。

セットアップ
デモプロジェクトのリポジトリーを解凍し、JBpss BPM Suite インストールプロジェクトディレクトリにコピーしてください。

# Start by cloning project at 
#   https://github.com/eschabell/demo-collections.
#
$ git clone git@github.com:eschabell/demo-collections.git

$ cd demo-collections

$ unzip niogit-rule-procvar-perinstance-strategy.zip

# Follow instructions and install JBoss BPM Suite 
# via https://github.com/eschabell/bpms-install-demo.
#
# Then copy the demo repository into the JBoss BPM Suite server.
#
$ cp -rv .niogit bpms-install-demo/target/jboss-eap-6.1/bin

# Start the JBoss BPM Suite server.
#
$ ./bpms-install-demo/target/jboss-eap-6.1/bin/standalone.sh

# Login with user 'erics' and password 'bpmsuite' to get started.

さて、これでビジネスプロセスを確認できます。プロセスはどのように設定されデプロイされていますか? ルールの内容は? プロセス変数の値を変更する為にどういった修正が必要ですか? 出力結果はどうなりますか?

ストラテジー

デプロイ単位でストラテジーを設定

前回の投稿で、セッション ストラテジーが SINGLETON である為、複数プロセスインスタンスが実行された場合、初回のインスタンスのみルールを実行することをご紹介しました。これは、メモリーの中にあるファクトが初回にファイヤーされたタイミングで削除され、それ以降のプロセスインスタンスがルールの実行を試みても、ワーキングメモリー内にはファクトが存在しない為です。

今回は、デプロイメントに設定するランタイム ストラテジーを PER_PROCESS_INSTANCE に変更します。このストラテジーを選択すると、プロセスインスタンスはそれぞれ個別のセッションを保有します。

ストラテジーを変更する為、JBoss BPM Suite のダッシュボードから Deploy -> Deployments ビューを選択し、既存のデプロイメントを削除してください。そして、新規デプロイメントを作成し、PER_PROCESS_INSTANCE ストラテジーを選択してください。

デプロイメント用の新しい デフォルト ストラテジー

作業が終了すれば、プロセスインスタンスを実行し、毎回ルールがファイヤーされることをご確認いただけます。その前に、SINGLETON セッション ストラテジー用に前回修正した内容を戻す必要があります。

毎回実行される為に修正されたルール
ワーキングメモリーに新しいオブジェクトがあるかチェックする行を削除します。

次に、ルールタスクノードの設定されたデータインプットセットを削除します。アサインメントにマップされたオブジェクトを削除してください。

修正作業が完了したらルールを保存し、デプロイ及びプロセスインスタンスの実行をしてください。プロセスインスタンスが実行される度に、ルールが実行されるはずです。

アサインメントのマッピングを削除
注意点ですが、プロジェクトエディターの Build & Deploy ボタンをクリックするかサーバーを再起動すると、上記で設定したデプロイメントの設定が失われます。

その場合は再び作成していただき、 PER_PROCESS_INSTANCE を忘れずに選択してください。そうしなければ、初回に実行されたプロセスインスタンスのみがルールを実行します。

3回プロセスインスタンスを実行し、成功した出力は以下の通りです。

11:35:47,038 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Execute Java Step
11:35:47,044 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Tested Rule
11:35:47,047 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Rule fired!
11:36:05,965 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Execute Java Step
11:36:05,968 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Tested Rule
11:36:05,970 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Rule fired!
11:36:10,479 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Execute Java Step
11:36:10,482 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Tested Rule
11:36:10,484 INFO  [stdout] (http-localhost/127.0.0.1:8080-3) Rule fired!

プロセスインスタンスビューからご確認いただくと、以下のように見えるはずです。


ルールを含んだプロセスがどのようにデプロイされたか理解いただけたと思います。また、ルールからプロセス変数へどのようにアクセスするかもご理解いただけたはずです。セッション ストラテジーによる影響もご理解いただけたはずです。ぜひ、このテクニックをあなたのプロジェクトにご活用ください。

原文: Red Hat JBoss BPM Suite - how to change runtime session strategy by Eric D. Schabell

2014年2月13日木曜日

Red Hat JBoss BPM Suite - ルールからプロセス変数にアクセスする

原文: Red Hat JBoss BPM Suite - accessing process context variables from a rule by Eric D. Schabell


今回の JBoss BPM Suite のヒント/トリック集では、BPMプロジェクトで使われるルールから、どうやってプロセス変数の値を更新するかご紹介します。

GitHubで公開しているデモコレクションでご確認いただけますが、シンプルなデモプロジェクトを使います。JBoss BPM Suite でお試しいただけます。

JBoss BPM Suite のインストール作業は別途実施していただく必要があります。JBoss BPM Suite インストールプロジェクトをご利用いただくことで、遭遇する可能性のあるトラブルを回避できます。

ゴール

この記事とデモプロジェクトのゴールは、ルールを使ったプロセスのデザイン方法をご紹介することです。ルールがファイヤーされると、プロセス変数の値を更新します。私はこのような、ビジネスプロセスとルール間の連携についてよく質問されます。

セットアップ

デモプロジェクトのリポジトリーを解凍し、JBpss BPM Suite インストールプロジェクトディレクトリにコピーしてください。

# Start by cloning project at 
#   https://github.com/eschabell/demo-collections.
#
$ git clone git@github.com:eschabell/demo-collections.git

$ cd demo-collections

$ unzip niogit-rule-procvar.zip

# Follow instructions and install JBoss BPM Suite 
# via https://github.com/eschabell/bpms-install-demo.
#
# Then copy the demo repository into the JBoss BPM Suite server.
#
$ cp -rv .niogit bpms-install-demo/target/jboss-eap-6.1/bin

# Start the JBoss BPM Suite server.
#
$ ./bpms-install-demo/target/jboss-eap-6.1/bin/standalone.sh

# Login with user 'erics' and password 'bpmsuite' to get started.

さて、これでビジネスプロセスを確認できます。プロセスはどのように設定されデプロイされていますか? ルールの内容は? プロセス変数の値を変更する為にどういった修正が必要ですか? 出力結果はどうなりますか?

初期の出力結果

ビジネスプロセスは、最初のノードでまずログを出力します。次に、ルールを実行します。(ここで、プロセス変数の値を修正する予定です) 次に、ルールがファイヤーされたかどうかで分岐するゲートウェイがあります。最後に、それぞれのパスでログを出力します。

プロセス変数の値を変えるルールを保有するビジネスプロセス
私たちがテストしたい内容は、左側にあるルールが変数を TRUE にすることで、右側にあるノードが「ルールがファイヤーされた」とログに出力することです。

初期の段階では、ビジネスプロセスに最初の 2ノードだけ持たせ、エンドノードに進むよう実装しました。もし 3プロセスインスタンスを実行したら、以下のようなログが出力されると予想しました。

17:29:46,315 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
17:29:46,330 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
17:29:46,315 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
17:29:46,330 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
17:29:46,315 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
17:29:46,330 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule

実際には、以下のログが出力されました。

17:29:46,315 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
17:29:46,330 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
17:29:46,315 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
17:29:46,315 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step

この時点で、私達はビジネスプロセスを上記でご覧いただいた画像イメージへ修正しました。ルールがファイヤーされたかどうか確認する為です。3プロセスインスタンスが実行されたら、以下のようなログが出力されると予想しました。

20:51:22,491 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step
20:51:22,494 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule
20:51:22,497 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired!
20:51:35,615 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step
20:51:35,618 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule
20:51:35,621 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired!
20:51:43,312 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step
20:51:43,316 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule
20:51:43,320 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired!

実際には、以下のログが出力されました。

20:51:22,491 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step
20:51:22,494 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule
20:51:22,497 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired!
20:51:35,615 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step
20:51:35,618 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Rule did not fire...
20:51:43,312 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step
20:51:43,316 INFO  [stdout] (http-localhost/127.0.0.1:8080-2) Rule did not fire...

2回目と 3回目にルールをファイヤーする時、何が起こったのでしょう?それだけではなく、2回目と 3回目にはルールがファイヤーされていないようです。なぜでしょうか?

この問題を解決する為には、デフォルト値として用意されているセッション・ストラテジーを確認する必要があります。

デプロイ

このビジネスプロセスがどのようにデプロイされたかよく確認してみましょう。デフォルト値である、SINGLETONが適応されていました。これは、すべてのプロセスインスタンスが1つの ksession で動作することを意味します。

デフォルト値である SINGLETONストラテジー でデプロイされている

プロセスはファクトをワーキングメモリーに投入し、プロセスを実行します。ルールタスクではルールを評価するでしょう。これが 1回目のプロセスインスタンスが行う処理内容です。

2回目以降は、ワーキングメモリーが更新されていない為、ルールは評価されません。ルールタスクでは何事も起きずに次の処理へ進みます。

この問題を修正する為、私達はプロセスをきれいにする必要がありました。ルールがファイヤーされた時に更新されるプロセス変数を用意し、ゲートウェイはプロセス変数を確認するように変更しました。ルールがファイヤーされていれば、ログにも記録します。覚えておいていただきたい点は、ルールがファイヤーされる時、プロセス変数の値を更新することです。

どのように修正されたか見てみましょう。

ルール

初期段階ではアクションをファイヤーさせる為、常に条件をマッチさせるべく以下の内容で実装しました。

rule "update-procvar"
ruleflow-group "fire-always"

when 
  eval(true)
then
  System.out.println("Tested Rule");
end

SINGLETON ksession では、初回はファイヤーされますが、2回目以降はファイヤーされません。修正する為には、プロセスインスタンスが実行される際、フォームオブジェクトもしくはファクトをワーキングメモリーに投入するよう修正する必要があります。

幸運にも、ルールタスクにはこのような機能が用意されています。データアサインメントを作成し、投入するデータセットをマッピングすることができます。ルールタスクを選択し、プロパティ画面を広げてください。fired という変数を用意し、nullを設定してあります。これをデータインプットセットとしてワーキングメモリーへ投入します。

fired 変数をワーキングメモリーへ毎回投入する為にマップ

import org.kie.api.runtime.process.WorkflowProcessInstance;

rule "update-procvar"
ruleflow-group "fire-always"

when 
  $pi: WorkflowProcessInstance()
  String()
then
  $pi.setVariable("fired", "true");
end

ルールの変更箇所について説明します。 import を追記することで、実行中のプロセスインスタンスにアクセスすることができます。ローカル変数 $pi を宣言することで、プロセス変数にアクセスすることができるようになります。新しい String オブジェクトが ワーキングメモリーにあるか確認する条件を追記しました。これは常に真となります。ルールタスクノードへ入る時、毎回 fired変数に設定したオブジェクトを投入していることを覚えていますか?

この修正によりルールは評価され、プロセスインスタンスが持つ fired変数の値は更新されます。この変更は、後続のゲートウェイノードで確認されます。

それでは実際に何回か実行し、結果を確認してみましょう。

出力結果


今、私達は問題を整理し、SINGLETON ksession を利用する意味を理解しました。それは、ワーキングメモリー内に変更があった場合のみ、新規プロセスインスタンス上でもファイヤーされるというものです。いよいよ、修正されたコードをテストしてみます。

3プロセスインスタンスを実行すると、以下の内容が出力されるはずです。

21:06:32,767 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
21:06:32,774 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
21:06:32,777 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Rule fired!
21:06:41,646 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
21:06:41,654 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
21:06:41,656 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Rule fired!
21:06:47,559 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
21:06:47,565 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
21:06:47,567 INFO  [stdout] (http-localhost/127.0.0.1:8080-5) Rule fired!

今回の記事を通して、ルールを含んだプロセスがどのようにデプロイされたか理解いただけたと思います。また、ルールからプロセス変数へどのようにアクセスするかもご理解いただけたはずです。ぜひ、このテクニックをあなたのプロジェクトにご活用ください。

原文: Red Hat JBoss BPM Suite - accessing process context variables from a rule by Eric D. Schabell

2014年2月12日水曜日

PHREAKアルゴリズムを使った Drools 6 のパフォーマンス

原文: Drools 6 Performance with the PHREAK Algorithm by Mark Proctor (Drools & jBPM)

Drools 6 では新しく lazy matchingアルゴリズムが導入されました。アルゴリズムの詳細については、以前 2つの記事で紹介しました。

さらば RETE、PHREAKの時代だ
Drools: PHREAK スタックベースの評価(Stack Based Evaluations)と逆行連鎖化(backward chaining)
※リンク先の記事は、和訳する予定です

最初の記事ではパフォーマンスについてと、アルゴリズムが持つバッチ処理と遅延評価機能がもたらすパフォーマンスを既存のアルゴリズムと比較することが何故難しいか説明しています。
パフォーマンスについて、最後に1点触れます。一般的に 1つのルールを評価するにあたり、RETEよりもPHREAKが早く動作することはありません。投入されたルールとデータセット(マッチングのオン/オフをコントロールするルートコンテキストオブジェクトが存在する前提)に対しては、どちらのアルゴリズムも同じ分評価し、ルールインスタンスを生成し、だいたい同じ処理時間が発生します。subnetwork と accumulate が使われるユースケースは別です。

下手に書かれたルールが増え複雑性が増すと、RETEのパフォーマンスは劣化しますが、PHREAK はさほど影響を受けません。

RETEはその他、すべてジョインされた中でデータを保持しないルールに対し、パーシャルマシンを生成することをやめてしまいます。PHREAK はこのような動作をしません。

よって、PHREAK は RETE より高速であるというわけではありません。運用されているシステムの規模が拡大しても、同じペースでパフォーマンスが低下しないということです :)

最近、OptaPlannerチームは ReteOO と Phreakに対して同じルールを使い、ベンチマークを取り始めました。
ルールエンジンのアルゴリズムはどっちが速い? ReteOO? Phreak?

記事によると、Phreak は ReteOO に比べ 3つのテストでは 20%高速で、1つのテストでは 4%低速でした。記事に記載されたコメントによると、17%のパフォーマンス差があったそうです。

OptaPlannerチームは、利用されたルールが Reteの制限に触れていないか、かなりの時間を使い確認しました。彼らは複数のバグを修正しました。例えば、1つのルールに複数の accumulate が存在する状況です。

あるユーザーは、ReteOO で問題となる書き方を使いルールを実装したらどうなるか興味を持ちました。Phreak がどれだけ優秀に処理するか気になったのです。彼は 4つルールを作成しました。個々のルールには 2つ accumulate があります。こちらからDRLファイルをダウンロードしていただけます。ルールのコピーを1つ掲載します。

rule gold_account
when
  account: Account()
  Number(this >= 50000) from accumulate(t: Transaction(source == account); sum(t.amount))
  Number(this >= 50000) from accumulate(t: Transaction(target == account); sum(t.amount))
then
  //System.out.println("Gold account: " + account);
end

結果は期待された通り、Phreak を使用すると 500%(5x)のパフォーマンス向上が計測されました : ) これは主に、Phreak がバッチでルールを評価し、たくさんの無駄な作業を辟けられたことに起因します。数段落前で別の記事の内容を引用しましたが、そこで述べられた狙いが当たった良い例と言えます。
下手に書かれたルールが増え複雑性が増すと、RETEのパフォーマンスは劣化しますが、PHREAK はさほど影響を受けません。

あなたもこのベンチマークを試されたい場合、こちらからプロジェクトをチェックアウトしてください。
https://github.com/winklerm/phreak-examples

このアルゴリズムはいまのところ、正確性と将来のマルチコア対応を考慮したスレッドの安全性に力を入れて設計されています。よって、まだ始まりに過ぎません。私達はまだ、たくさんの最適化案や改善案を持っています。

原文: Drools 6 Performance with the PHREAK Algorithm by Mark Proctor (Drools & jBPM)

2014年2月11日火曜日

Red Hat JBoss BPM Suite - SSH を使って GITプロジェクトにアクセスする

原文: Red Hat JBoss BPM Suite - access GIT project using SSH by Eric D. Schabell

記事のタイトルは、JBoss BRMS / BPM Suite v6 が先週リリースされてから私が頻繁に質問されたトピックのうちの1つです。

この記事では JBoss BRMS のスーパーセットである JBoss BPM Suite を利用して解説します。よって、これから解説される内容は、どちらの製品にも利用できます。

リポジトリーが GITベースになったことで、新しい開発/デプロイモデルを使用する必要があります。

JBoss BPM Suite のアーキテクチャーをよく見てみると、ビジネスユーザーと開発チームが繋がっているリポジトリーは GIT リポジトリーであることがわかります。

JBoss BPM Suite アーキテクチャー
一般的なワークフローを考えてみます。JBoss BPM Suite が提供するウェブベースの GUIツールである モデルデザイナー、プロセスデザイナー、ルールデザイナーをビジネスアナリスト達が利用するでしょう。そうすることで、彼等の作業内容は一箇所に集約されます。この作業の後(もしくは並行して)、開発者達はアプリケーションを開発し、ビジネスアナリスト達の作業を助けるでしょう。

初期のベータリリース版を使って作業していた頃、私達はセキュアーではない gitプロトコルを利用していました。その為、認証作業をせずに clone や push をしていました。例えば、「一般的なローンのデモ」で行ったプロジェクトの読取専用コピーをクローンする作業がそうでした。

$ git clone git://localhost/bpms-generic-loan

Cloning into 'bpms-generic-loan'...
remote: Counting objects: 266, done
remote: Finding sources: 100% (266/266)
remote: Getting sizes: 100% (213/213)
remote: Compressing objects:  51% (110/212)
remote: Total 266 (delta 22), reused 133 (delta 19)
Receiving objects: 100% (266/266), 47.97 KiB, done.
Resolving deltas: 100% (54/54), done.

GA版の製品では、認証作業をせずに修正内容を push することはできません。
もし実施した場合、以下のようなエラーが出力されるはずです。

$ git push

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

clone や push を実行する際、SSHプロトコルを利用する必要があります。「一般的なローンのデモ」を例にすると、以下の作業が必要になります。

プロジェクトをセキュアーに clone する

$ git clone ssh://erics@localhost:8001/bpms-generic-loan

Cloning into 'bpms-generic-loan'...

The authenticity of host '[localhost]:8001 ([127.0.0.1]:8001)' can't be established.
DSA key fingerprint is 62:c2:c5:4c:22:3a:dd:8e:24:34:bf:3f:16:e7:3c:73.
Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added '[localhost]:8001' (DSA) to the list of known hosts.
Authenticated with partial success.
Password authentication

Password: bpmsuite   <<<<< enter-password-here

remote: Counting objects: 266, done
remote: Finding sources: 100% (266/266)
remote: Getting sizes: 100% (213/213)
remote: Compressing objects:  51% (110/212)
remote: Total 266 (delta 22), reused 133 (delta 19)
Receiving objects: 100% (266/266), 47.97 KiB, done.
Resolving deltas: 100% (54/54), done.

プロジェクトをセキュアーに push する

$ git push

Authenticated with partial success.
Password authentication

Password: bpmsuite   <<<<< enter-password-here

Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 282 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2)
remote: Updating references: 100% (1/1)
To ssh://erics@localhost:8001/bpms-generic-loan
   f789a22..659ef75  master -> master

今回の記事で、JBoss BPM Suite を利用した BPMプロジェクトの開発をする際、役に立つ知識が増えることを願います。

原文: Red Hat JBoss BPM Suite - access GIT project using SSH by Eric D. Schabell

2014年2月7日金曜日

シカゴ JBUG レポート - JBoss エバンジェリスト ツアー

原文: Chicago JBUG Report - JBoss Evangelists on Tour by Eric D. Schabell


以前 お伝えしたとおり、今週はシカゴで特別な JBUGイベントを開催しました。JBossのエバンジェリストが全員集まったイベントだったのです。

18度と予報されていた気温は、冷たい風により -28度 まで下がりました。

この天候の中、終日行われるイベントの為にオフィスまで来ていただけるか難しい判断でしたが、私たちは予定通りの開催に踏みきりました。そして、Java EE、JBoss EAP、JBoss BRMS、JBoss BPM Suite、JBoss DV、JBoss FSW と多様なテーマについて発表しました。

参加者は、より深く知りたいトピックを選ぶことができ、選んだトピックに関するワークショップ用の教材が配布されました。自宅で遊んでいただく為です。

私のセッションでは、JBoss BRMS と JBoss Suite 入門を紹介し、簡単なサンプルを含むワークショップを提供しました。

使用したスライドを公開します。







原文: Chicago JBUG Report - JBoss Evangelists on Tour by Eric D. Schabell