Apache Inference APIについて

# はじめに
[前回の記事](https://qiita.com/Takashi_Kasuya/items/b5cddeed58934e58a085)のOntology APIに続いて、Inference APIの解説です。Jenaでは、Ontology APIによるモデルの取り扱いと、推論（Inference, Reasoning)が別のモジュールで提供されているのが特徴です。Jenaで取り扱い可能なReasonerは以下とのこと。他には[Pellet](https://github.com/stardog-union/pellet)なんかが有名で論文なんかにも取り上げられていますが、Stardogのプロダクトに吸収されたようですね。

1. **Transitive reasoner** : Transive / Reflexiveなプロパティーのみ受け付ける。具体的には`rdfs:subPropertyOf`と`rdfs:subClassOf`。
2. **RDFS rule reasoner** : RDFSを含む構成可能なサブセット。
3. **OWL, OWL Mini, OWL Micro Reasoners** : その名の通り。OWLのサブセットなど。
4. **Generic rule reasoner** : ルールベースのReasonerでユーザが自分で実装できる。普通は使わなそう。

# Reasoner
推論を行うのはReasonerと呼ばれるコンポーネントです。Reasonerを使って推論モデル（InfModel）を使って、推論のオペレーションをするというのが基本的な流れです。

Reasonerは通常はファクトリーメソッドを介して生成されます。事前に用意されたReasonerがあるようですが、Ontology APIを使っている場合、事前に生成されたOntModelSpecが適当なReasonerを当てはめてくれるようです。例えばシンプルなRDFモデルをRDFSを使って推論する場合、`ModelFactory.createRDFSModel`が使われます。以下のような感じです。

```java

String NS = "urn:x-hp-jena:eg/";

// 適当なモデルを作る
Model rdfsExample = ModelFactory.createDefaultModel();
Property p = rdfsExample.createProperty(NS, "p");
Property q = rdfsExample.createProperty(NS, "q");
rdfsExample.add(p, org.apache.jena.vocabulary.RDFS.subPropertyOf, q);
rdfsExample.createResource(NS+"a").addProperty(p, "foo");

// RDFSを使ったReasonerによるInfModel
InfModel inf = ModelFactory.createRDFSModel(rdfsExample);
```

上記ではpというプロパティに`rdfs:subPropertyOf`という述語を記述し、対象をqとしました。そうすると、推論が働いて、qというプロパティを参照するとpの内容（すなわち`foo`)が取得できます。

```java
Resource a = inf.getResource(NS+"a");
System.out.println("Statement: " + a.getProperty(q));
```

上記のやり方以外にも、Reasonerに対して色々と設定を事前に行いたい場合は、以下のようにResonerを分けてInfModelを作ることもできます。


```java
Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(null);
InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample);
```
## 色々なReasoner
### The RDFS Reasoner(RDFSRuleReasoner)
Jenaにデフォルトで含まれる推論器で、RDFSをサポートします。３つの適合レベルがあり、設定時に指定できます。以下の例ですと、`ReasonerVocabulary.PROPsetRDFSLevel`で指定しているところですね。

```java
Resource config = ModelFactory.createDefaultModel()
                  .createResource()
                  .addProperty(ReasonerVocabulary.PROPsetRDFSLevel, "simple");
Reasoner reasoner = RDFSRuleReasonerFactory.theInstance()Create(config);
```


1. **Full** : すべての公理、規則等を含む。
2. **Default** :　高負荷なチェックを排除したもの。よくわかってませんが、"everything is a resource"と"everything used as a property is one" (rdf1, rdfs4a, rdfs4b)の２つのルールがないようで実用上はこれでほとんど問題ないらしいです。
3. **Simple**　：subPropertyOf, subClassOfといった推移的な関係、およびdomain, rangeといった範囲記述などのみを含むもので、公理（axiom)は含まない。最も便利そうな気がするけれど、不完全な実装のためにデフォルトにはなっていない。

### The OWL Reasoner 
Jenaで提供しているのは、OWL/fullのサブセットであるOWL/Liteの実装で、現状では設定でデフォルトとFaster/Smallerの二つのモードを指定できるとのこと。OWL/Fullの完全な実装を目指しているのではないので、Pellet、[Racer](https://franz.com/agraph/racer/racer_features.lhtml)、FaCTといった別なエンジンを使ってくれとのこと。使い方としては以下のような感じです。OWLで記述したオントロジー（schema）を読み込んで、reasonerにバインドしてからInfModelを作っています。

```
Model schema = FileManager.get().loadModel("file:data/owlDemoSchema.owl");
Model data = FileManager.get().loadModel("file:data/owlDemoData.rdf");
Reasoner reasoner = ReasonerRegistry.getOWLReasoner();
reasoner = reasoner.bindSchema(schema);
InfModel infmodel = ModelFactory.createInfModel(reasoner, data);
```

今日はここまで。
このくらいの情報あれば、オントロジーによる推論を使ったアプリはとりあえず作れるかなと…

# 参考
- [Reasoners and rule engines: Jena inference support](https://jena.apache.org/documentation/inference/index.html)
- [Extracting knowledge from Ontology using Jena for Semantic Web](https://www.researchgate.net/publication/275637920_Extracting_knowledge_from_Ontology_using_Jena_for_Semantic_Web)
- [Reasoning in Semantic Web Using Jena](https://pdfs.semanticscholar.org/979e/d987b45bbbd6635aa47fe4a37a6d88cb9c6f.pdf)