kogito-examples 利用例

WIP : たまに追加していきます

各プロジェクトで mvn clean package quarkus:dev

dmn-quarkus-example

リクエス

curl -d '{ "Driver": { "Points": 2}, "Violation": { "Type": "speed", "Actual Speed": 120, "Speed Limit": 100 }}' -H "Content-Type: application/json" -X POST http://localhost:8080/Traffic%20Violation

レスポンス

{"Violation":{"Type":"speed","Speed Limit":100,"Actual Speed":120},"Driver":{"Points":2},"Fine":{"Points":3,"Amount":500},"Should the driver be suspended?":"No"}

イタリア語

www.17-minute-world-languages.com

  • おはようございます!
    • Buon giorno! ボン・ジョールノ
  • こんにちは!
    • Buon giorno! ボン・ジョールノ
  • こんばんは!
    • Buona sera! ボナ・セーラ
  • おやすみなさい
    • Buona notte! ボナ・ノッテ
  • バイバイ!
    • Ciao! チャオ
  • さようなら!
    • Arrivederci! アリベデルチ
  • はい
    • Si. シィ
  • いいえ
    • No. ノ
  • わかりました
    • Ok.
  • ありがとう!
    • Grazie! グラツィエ
  • どういたしまして!
    • Prego! (Di niente)
  • すみません、
    • Scusi ...
  • ごめんなさい。
    • Mi dispiace.
  • 私の名前は Toshiya Kobayashi です
    • Il mio nome è Toshiya Kobayashi

MS SQL Server 備忘録

SQL Server Management Studio

SQL実行

"New Query" / File->New->Query with...

SQL Server Management StudioでSQLを実行する方法 | SQLServer初心者でもスッキリわかる

ミリ秒計測(SSMSで)

set statistics time on

<query>

set statistics time off

で、"Message"タブを見る

インデックス確認

 SELECT
     convert(varchar, i.name) AS index_name
     , convert(varchar, o.name) AS table_name
     , convert(varchar, col.name) AS column_name
 FROM
     sysindexkeys ik
     ,sysobjects o
     ,syscolumns col
     ,sysindexes i
 WHERE
         ik.id = o.id
     AND ik.id = col.id
     AND ik.colid = col.colid
     AND ik.id = i.id
     AND ik.indid = i.indid
     AND o.xtype = 'U'
     AND o.name in ('NodeInstanceLog', 'AuditTaskImpl')
 ORDER BY
     i.name
     ,ik.id
     ,ik.indid
     ,ik.keyno

Droolsブログ : 08 no-loop, lock-on-active

08 no-loop, lock-on-active

DRL には様々な属性(attribute)を指定することができます。

https://docs.jboss.org/drools/release/7.26.0.Final/drools-docs/html_single/#_rule_attributes

今回はそのなかで、no-loop と lock-on-active を紹介します。

サンプルコードはこちらから clone してください。

git clone https://github.com/tkobayas/drools-blog.git

今日のエントリはその中の 08_noloop_lockonactive です。

03 推論」のときのルールをベースにしています。このとき私が

ここで「あれ? "春のキャンペーン" や "高額商品キャンペーン" も再評価されて2重に実行されたりしないの?」と疑問に思った人もいるかも知れません。実は重要なポイントです。さっき「$o が更新されたよ、と伝える」と書きましたがこのときルールエンジンは $o のどのプロパティが変更されたかを意識します。つまり $o の extraPoint が変更された、と知っているので consumer や itemPrice は再評価しないのです。これは「Property Reactive」という機能で

と書いていたのを覚えているでしょうか。要するに Drools は変更されたプロパティと関係のないルールは再評価しない、ということです。しかし、「変更されたプロパティと関係あるルールだけど再評価して欲しくない」というパターンもありえます。今回のルールを見てください。

rule "春のキャンペーン"
    //no-loop true
    //lock-on-active true
    when
        $o : Order(consumer.memberCreatedAt >= "2019-04-01" && consumer.memberCreatedAt <=  "2019-04-30", extraPoint < 20000)
    then
        System.out.println("実行 : " + kcontext.getRule().getName());
        $o.setExtraPoint($o.getExtraPoint() + 2000);
        update($o);
end

rule "高額商品キャンペーン"
    //no-loop true
    //lock-on-active true
    when
    $o : Order(itemPrice > 100000, extraPoint < 20000)
    then
        System.out.println("実行 : " + kcontext.getRule().getName());
        $o.setExtraPoint($o.getExtraPoint() + 4000);
        update($o);
end

2つのルールに「extraPoint < 20000」という条件が足されています。20000以上のエクストラポイントのオーダーはマッチしないようにしよう、ということです。さて、この場合ルールが実行されると extraPoint が更新されるのでルールが再度ヒットします。試してみましょう。

$ mvn test
...

insert : Person [name=ジョン, memberCreatedAt=2019-04-11]
insert : Order [consumer=ジョン, itemName=ギター, itemPrice=200000, specialPointOrder=false]
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 春のキャンペーン
実行 : 大量ポイント獲得オーダー
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.842 sec <<< FAILURE!
testHello(org.example.DroolsTest)  Time elapsed: 1.79 sec  <<< FAILURE!
java.lang.AssertionError: expected:<3> but was:<11>

「春のキャンペーン」が繰り返し実行されてしまいましたね。。。ここでまず「no-loop」という属性があります。これは「自分自身を繰り返して実行しない」という属性です。2つのルールに「no-loop true」という行がコメントで書かれているので、コメントをはずして実行してみましょう。

insert : Person [name=ジョン, memberCreatedAt=2019-04-11]
insert : Order [consumer=ジョン, itemName=ギター, itemPrice=200000, specialPointOrder=false]
実行 : 春のキャンペーン
実行 : 高額商品キャンペーン
実行 : 春のキャンペーン
実行 : 高額商品キャンペーン
実行 : 春のキャンペーン
実行 : 高額商品キャンペーン
実行 : 春のキャンペーン
実行 : 大量ポイント獲得オーダー
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.599 sec <<< FAILURE!
testHello(org.example.DroolsTest)  Time elapsed: 1.546 sec  <<< FAILURE!
java.lang.AssertionError: expected:<3> but was:<8>

残念!今度は「春のキャンペーン」と「高額商品キャンペーン」が交互に実行されています。「no-loop」は「自分自身の繰り返し」にしか効かないのです。無力、あまりに無力。。。

このような場合は「lock-on-active」の出番です。「no-loop」は再度コメントアウトし、「lock-on-active true」の行のコメントをはずして実行してみましょう。

insert : Person [name=ジョン, memberCreatedAt=2019-04-11]
insert : Order [consumer=ジョン, itemName=ギター, itemPrice=200000, specialPointOrder=false]
実行 : 春のキャンペーン
実行 : 高額商品キャンペーン
実行 : 大量ポイント獲得オーダー
======================================
ポイントキャンペーンのご活用ありがとうございます!
======================================
----
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.533 sec

うまくいきましたね!「lock-on-active」は「一度呼ばれると二度と再実行されない(ruleflow-group/agenda-groupが変わらない限り)」です。こちらのほうが no-loop より求められていることが多いでしょう。

今日はここまで!

OptaPlanner 備忘録

XStream の input ファイルが reference を XPATH で書いている場合

<com.example.MySolution>
  <id>1</id>
  <locationList>
    <com.example.model.Location>
      <id>0</id>
      <name>xxxx</name>
    </com.rekeep.domain.model.Location>
  </locationList>
  <officeList>
    <com.example.model.Office>
      <id>0</id>
      <location reference="../../../locationList/com.example.model.Location" />
    </com.example.model.Office>
    ...
com.thoughtworks.xstream.converters.ConversionException: Invalid reference

にヒットする。

		XStreamSolutionFileIO<EmployeeRoutingSolution> xStreamSolutionFileIO = new XStreamSolutionFileIO<>(MySolution.class);
		xStreamSolutionFileIO.getXStream().setMode(XStream.XPATH_RELATIVE_REFERENCES);
		File inputFile = new File("src/test/resources/input/test_input.txt");
		MySolution inputSolution = xStreamSolutionFileIO.read(inputFile);

のように mode を指定する。

solution の スコア計算だけする

保存しておく

		File outputFile = new File("src/test/resources/output/my_test_OUTPUT1.txt");
		xStreamSolutionFileIO.write(bestSolution, outputFile);

読み出してから

		ScoreDirector<MyRoutingSolution> scoreDirector = solver.getScoreDirectorFactory().buildScoreDirector();
		scoreDirector.setWorkingSolution(inputSolution);
		Score score = scoreDirector.calculateScore();

inputSolution を編集して、再計算することもできる

Droolsブログ : 07 MVEL

07 MVEL

MVEL というのは Java ベースの言語で、 Java をより簡単に表記する事を目的にしています。超ざっくり言うと、getter/setter を省略して書いたりできます。

user.name == 'ジョン レノン'

ドキュメントはこちらを参照ください。

http://mvel.documentnode.com/

Drools ではルールを簡便に書くために MVEL を内部的に利用しています。大きく分けると 3つの箇所で、MVEL が使用されます。

1) ルール制約(Constraint)

例えば

        $p : Person( age >= 26 )

の age >= 28 の部分は はじめは MVEL によって処理されます。よって先程書いた getter の省略などが可能です。

「はじめは」 って書きましたね。実はこの制約部分は20回実行されると動的に Java クラスが生成、コンパイルされ、以降は MVEL ではなく Java クラスとして実行されます。JVMJIT と同じような考え方で、よく実行される部分は最適化してパフォーマンスを上げようというものです。

ただ「いや、そもそも最初から Java クラス生成すればいいんじゃね?」という意見から、もうその方向に開発が進んでいます。これは executable-model というオプションで、すでに Drools 7 では利用可能です。おそらくバージョン 8 ではデフォルトの動作になるでしょう。

いずれにせよユーザにとって内部的な挙動は気にしなくてもよいのですが、「しばらく実行したあとに突然ルールの挙動が変わった」ような問題が発生した場合は、動的な Java クラス生成時のバグが原因だった、なんてこともあります。

2) eval

以下のように eval という文法が使えます。

  dialect "mvel"
  when
    $p1 : Parameter()
    $p2 : Parameter()
    eval($p1.list.contains( $p2.item ))

これは eval() 内部をまるごと Java もしくは MVEL で解釈し、true が返ればルールにマッチする、というものです。上記のように dialect に "mvel" を宣言した場合、MVELで記述できます。 Java 的なロジックをゴリゴリ書けるので、一部で好まれるのですが、Drools エンジンからは最適化ができないのでパフォーマンス上おすすめしません。極力普通のフィールド制約で記述するのが Drools のパフォーマンスを上げるコツです。また、eval は近いうちに deprecated になるのではないかと言われています。

3) RHS

ルールの RHS (then の部分です)を MVEL を使って表記できます。その場合、上記と同様

  dialect "mvel"

を宣言する必要があります。dialect は package 単位もしくは rule 単位で宣言できます。"mvel" 以外には "java" があります。デフォルトは "java" です。

ここで MVEL を使うメリットは。。。 BigDecimal の四則演算が簡単だからです。理由の9割くらいがそれですね。(あと getter/setter が無いと日本語フィールド名が見やすいとか)

    then
        $p.salary = $p.salary + 50000;
end

ただここまで説明しておいてなんですが、Drools チームは MVEL への依存を無くす方向へ進んでいます。ですので、新規開発では、できれば 2 と 3 の利用方法は避けていただいたほうがよいのではないかと思います。(1 は executable-model で内部的に変更される)

サンプルコードはこちらから clone してください。

git clone https://github.com/tkobayas/drools-blog.git

今日のエントリはその中の 07_mvel です。

このようなルールです。eval は使っていません。

https://github.com/tkobayas/drools-blog/blob/master/07_mvel/src/main/resources/org/example/Sample.drl

package org.example
 
import org.example.Person;

dialect "mvel"

rule "昇給"
    when
        $p : Person( age >= 26 )
    then
        $p.salary = $p.salary + 50000;
end

実行すると

$ mvn clean test

...
Running org.example.DroolsTest
...
ジョン の給料は 350000円です。
...

ルール通りに出力されましたね。