Grakn.ai - 定義していない暗黙の関連性をグラフから導き出す。Grakn流の知識表現（Knowledge Representation & Reasoning)

##はじめに
[Database for AI - Grakn.aiことはじめ part 1 - エンジニアマインドでいじれるグラフDB](https://qiita.com/ShinHashitani/items/3e6b9365d070f561931f)でも少し触れたが、そもそも数ある（という程でもないが）グラフDBの中からGraknに注力した理由は、オントロジー層を持つGrakn流のKR（知識表現）に可能性を感じたからである。最初からセマンティックウェブを構築するつもりはなく、あくまで特殊なデータの特殊な扱い方という用途を考えた時に、Graknのアプローチはしっかりハマるように感じたし、触り始めて3週間経った今でもその思いは変わらない。とりあえず本番環境にどう持っていこうだとか、運用はどうしようだとか、GAはいつになるだろうかとか、そのあたりはしばらくすっかり忘れて機能性にのみ注力していきたい。

Inferenceは、Graknにおけるコアな概念であり、最初のとっかかりには少し苦労する。まずは基本的なところをしっかり押さえる方が良い、と思う。今回はこの基本的なところをじっくり説明したい。
##KR (Knowledge Representation & Reasoning)とは
KRとは人工知能領域の一つで、複数の知識表現をもってInference（推論/演繹）を導き出す事を目的とした学問である。機械学習のようにInputとOutputの膨大な組み合わせから高確率の回答を導き出す手法とは異なり、あくまで知識表現の各要素は明示的に定義したものであり、その組み合わせ方法と演算方法の定義等によって回答を求める。
らしい。詳しくは[wikipedia - 知識表現](https://ja.wikipedia.org/wiki/%E7%9F%A5%E8%AD%98%E8%A1%A8%E7%8F%BE)をどうぞ。情報処理の教科書的にいうと、「エキスパートシステム」がやろうとしている事もKRにあたり、Graknを使ったKRもその一種と考えてもらっていい。
####GraknとKR
Graknの定義する解法自体は、実はさほど新しいものでは無い。知識フレームと呼ばれる方法論を周到しており、その為オントロジーはオブジェクト指向的な継承の性質を含む。使用される"is-a"といったリンク機能も知識フレームの概念とほぼ同じ。これがグラフDB上に構築され、かつ関連の整合性をオントロジーを継承であり制約として定義することにより知識フレームにおけるエンティティの矛盾定義を取り除いているところに意味がある。

さらに、エキスパートシステムでは各ドメイン毎にモデリングには専門知識を要するほどデリケートなもので、実社会ではコストばかり嵩んでメリットがほとんど出なかった。Graknは制約を元にした簡素化したオントロジーによって、一般的なオブジェクト指向の理解とシステム分析の能力があれば比較的容易にモデリング出来る点も重要な特性である。創業者のHaikal PribadiさんがData Day Texas 2017で公演された[How to Work with Large and Complex Graphs.](https://www.youtube.com/watch?v=OeFrudRlXAM)がとても分かり易い（英語でごめん）のだが、ちょっとJavaをかじったSEであれば「出来んじゃない？」と思わせる説得力がある。この「エンジニアリング出来るグラフDB」というキャッチコピーが、Graknにはとてもしっくりくる。そう、グラフだろうがなんだろうがモデリングはモデリング、の心意気で触れてみて欲しい。

そう、「制約」は正義である。フレームワークなんかを設計していると分かるが、自由度とフレームワークのシステムに対する貢献度はトレードオフの関係にあり、自由になれば自分で書かないといけない事が増え、プラットフォームを間違って使うケースも増える。習熟難易度（ラーニングカーブ）はだいたい制約と比例し、システムのバグ検出率は自由度にだいたい比例する。Graknのオントロジーモデルは、制約を上手く使って概念の持つ問題を解消している良い例だと思う。

##Inferenceとは
つまるところ、Inferenceとは「明示的に定義していない関連性をDBが理解する」ということになる。これだと抽象的過ぎてほんとにAIに聞こえてしまうが、ここでの「明示的」とは具体的にノード間の関係を明示しないだけで、関係の定義は存在するものでなければならない。ますます何が言いたいの分かりにくくしてしまってるが、まずはRelationshipにも2パターンあるところから始めよう。

#### Relationshipオブジェクト
RelationshipはGrakn上全ての要素のスーパークラスであるThingを直接継承した一人前のクラスであり、Entityと同等。Java等オブジェクト指向言語で表現されるRelationshipはもっと緩いものであり、リレーショナルモデルでもRelationshipは具現化されるものではない。Graknでは（グラフDBではそうなのだが）エンティティと並ぶ要素の主であり、データとして定義され格納される。当然データの登録にはinsertが必要。

insertは関連性の対象となる双方のEntityへの参照が必要で、構文がEntityとはやや異なるが扱いは同等である：

```Bash
#Entityの場合
insert $product isa product, has name "こだわり外貨終身";
insert $coverage isa coverage, has name "主契約";

#Relationshipno場合
insert $product-coverage isa benefit-hierarchy
(product: $product, coverage: $coverage); 
```

####Inference Rule
Graknでは具現化されない、非明示的なRelationshipも存在し、これがInference Ruleと呼ばれるものである。Ruleとあるのでお察しの方もいるかと思うが、ここでは明示的な参照では無く「条件」を記載する事によって関連性を定義する。そして、ここがキモなのだが、条件の結果として生成されるものはRelationshipであり、明示的に定義するRelationshipとクエリ上差は無い。ルールを足すことによって、さっきまで1つしか取得できなかった要素が複数個取得されたりする、そしてどの要素がDBに格納されているRelationshipなのか、Inference Ruleの条件に基づいて算出されたRelationshipなのか、クエリが意識する事は無い。

Inference Ruleはデータ投入では無い為insertではなくオントロジーの定義で使用するdefineキーワードを使用して定義する：

```Bash
define delegate-limitation-product-coverage sub rule,
  when {
    $product isa product;
    $coverage isa coverage;
    ($product, $coverage) isa benefit-hierarchy;
    ($product, $limit) isa condition-limit;
  } then {
    (limited-by:$coverage, limits:$limit) isa condition-limit;
  };
```

ここではまず、productとcoverageというEntityを特定。そしてproductとcoverageの親子関係をbenefit-hierarchyというRelationshipで特定してあり、productに紐付く制約条件もcondition-limitというRelationshipで特定。これら全ての条件を満たす場合、暗黙的に同じproductに紐付けられたlimitをcoverageにも適用するRelationshipとして定義している。つまりは「商品（product）の制約事項(limit)は、その商品の保障(coverage)にも適用される」ということを表している。

これは単純なようで非常に重要で、この「当たり前の事」を当たり前に書けるのがInference Ruleの強みである。
##もう少しInferenceに踏み込んでみる
この仕組みは階層的になっているデータモデルに対して非常に上手く機能する。もう少しいくつか例を挙げてみる。
####先祖と子孫
おじいちゃんとお父さんと子供。それぞれの直接的な関係性を定義するのは簡単：

```Bash
define
person sub entity
  plays parent
  plays child;

parentship sub relation
  relates parent
  relates child;
parent sub role;
child sub role;	

$grandpa isa person;
$father isa person;
$son isa person;
(parent:$grandpa, child:$father) isa parentship;
(parent:$father, child:$son) isa parentship;
```

これでもクエリで三人の関連性をグラフとして抜き出すことは出来る：

```Bash
match
$grandpa isa person;
$father isa person;
$son isa person;
(parent:$grandpa, child:$father) isa parentship;
(parent:$father, child:$son) isa parentship;
get;
```

ただ、この場合定義された関連性は**おじいちゃん-おとうさん**、**おとうさん-子供**と個別のRelationshipとなっている。この為、「おじいちゃんの子孫を全員」とか「子供の先祖を全員」といった事実は人間にとっては自明だが、DBにとっては定義の無い知らない関連性である。このモデルはリレーショナルモデルは苦手。これを、GraknではInference Ruleを足すことで自明に出来る。

```Bash
define
person sub entity
  plays parent
  plays child
  plays ancestor  #追加
  plays descendant;  #追加  

#ちょっと変更。
ancestory sub relation
  relates ancestor
  relates descendant;
ancestor sub role;
descendant sub role;

#Inference Rule
define
ancestory-rule sub rule,
  when {
    (ancestor:$granpa, descendant:$father) isa ancestory;
    (ancestor:$father, descendant:$son) isa ancestory;
  } then {
    (ancestor:$granpa, descendant:$son) isa ancestory;
  }; 
```

これで、子供からancestorを取りに行ったとき、お父さんだけでなくおじいちゃんも同様に抽出できるようになる。このルール1本でおばあちゃん-おかあさん-娘も、そしてそのいかなるバリエーションも適切に抽出できる。しかも、クエリ条件等を指定しなくても、定義したールールにそってあたかもRelationshipが定義されているかのように抽出できる。徳川家のようなとてつもなく家系図が複雑になった場合にも有効。
####その他の例
家系図がGrakn.aiの本家にもある有名なケースだが、例えば日本-関東-東京-世田谷区-三軒茶屋のような関連性で「三軒茶屋は日本に属する」といったInferenceや、組織階層のレポートラインなんかもサクッと取れる。データの扱いでこのような階層データは良く出てくるもので、適用範囲は意外と広いし、かつ便利。
##おわりに
もちろんInferenceは階層構造のデータにしか適用できない訳ではない。本家[Grakn Academy](https://grakn.ai/pages/academy/index.html)では[Database for AI - Grakn.aiことはじめ part 2 .1 - Oracle Virtual Boxで学ぶGrakn Academy](https://qiita.com/ShinHashitani/items/e5e162c5958f819d1a40)で紹介したように少し複雑なケースを順序立てて説明してくれておりとても分かり易いのでお勧めしたい。（ビジネスドメイン自体がちょっと分かりにくいが。）この機能と、Grakn特有の継承型エンティティモデルを使うと、かなり柔軟かつシンプルに、そして何よりエンジニアにとってとても分かり易い手法でオントロジーを定義する事が出来る。