Szkoła Web 3.0 Dowiedz się czym jest Sieć Semantyczna

3lis/09Off

Nasz pierwszy semantyczny program z biblioteką Jena

Wczoraj otrzymałem ciekawy komentarz/zapytanie do artykułu o wnioskowaniu z RDF Schema. Ponieważ przykład daje więcej niż tysiące opisów i wyjaśnień postanowiłem pokazać jak łatwo można wykonać wnioskowanie z RDF Schema korzystając z biblioteki Jena, o której pisałem niedawno.

Jena jest biblioteką dostarczającą API w języku Java. Zacznijmy więc od zebrania potrzebnych narzędzi:

W Eclipse rozpoczynamy nowy projekt typu Java, i przegrywamy i dodajemy do projektu JARy dostarczone z biblioteką Jena:

Jena i biblioteki zależne

Następnie tworzymy nową klasę i zaczynamy nasz pierwszy "semantyczny" program. Polecam specyfikację biblioteki Jena: http://www.openjena.org/javadoc/index.html.

Zdefiniujmy dwie przestrzenie nazw, jedną na elementy ontologii w RDF Schema, a drugą na zasoby:

static final String NS_ONT = "http://www.semanticschool.com/rdfs#";

static final String NS_DATA = "http://www.semanticschool.com/data#";

Następnie tworzymy nowy model, czyli obiekt który będzie reprezentował tworzony przez nas graf RDF; pamiętajmy że RDF Schema jest również zapisana w postaci grafu RDF.

Model model = ModelFactory.createDefaultModel();

W następnym kroku dodajemy do modelu definicje naszych klas i właściwości.

//[semschool:Samochod] [rdf:type] [rdfs:Class].

Resource cSamochod = model.createResource(NS_ONT+"Samochod");

cSamochod.addProperty(RDF.type, RDFS.Class);

//[semschool:Czlowiek] [rdf:type] [rdfs:Class].

Resource cCzlowiek = model.createResource(NS_ONT+"Czlowiek");

cCzlowiek.addProperty(RDF.type, RDFS.Class);

//[semschool:kierowac] [rdf:type] [rdf:Property].

Property pKierowac = model.createProperty(NS_ONT, "prowadzi");

pKierowac.addProperty(RDF.type, RDF.Property);

pKierowac.addProperty(RDFS.domain, cCzlowiek);

pKierowac.addProperty(RDFS.range, cSamochod);

W tym momencie możemy wypisać nasz graf RDF:

model.write(System.out, "N-TRIPLE");

otrzymamy w następujący wynik (z dokładnością do kolejności trójek):

<http://www.semanticschool.com/rdfs#prowadzi> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.semanticschool.com/rdfs#Samochod> .

<http://www.semanticschool.com/rdfs#prowadzi> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.semanticschool.com/rdfs#Czlowiek> .

<http://www.semanticschool.com/rdfs#prowadzi> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> .

<http://www.semanticschool.com/rdfs#Czlowiek> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> .

<http://www.semanticschool.com/rdfs#Samochod> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> .

W kolejnym kroku stwórzmy nowy model bazujący na poprzednim. Model ten nie będzie wykorzystywał wnioskowania bazującego na RDF Schema (tzw. inferencing)

Model model2 = ModelFactory.createDefaultModel();

model2.add(model);

A następnie dodajmy do niego dwa zasoby: [Jan] i [Mazda], oraz stwórzmy zdanie [Jan] [kieruje] [Mazdę].

Resource rJan = model2.createResource(NS_DATA+"Jan");

Resource rMazda = model2.createResource(NS_DATA+"Mazda");

rJan.addProperty(pKierowac, rMazda);

I ponownie jak poprzednio wypiszmy nasz obecny graf:

model2.write(System.out, "N-TRIPLE");

Jak widać poniżej, w wyniku doszło tylko jedno dodatkowe zdanie RDF:

<http://www.semanticschool.com/rdfs#prowadzi> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Property> .

<http://www.semanticschool.com/rdfs#prowadzi> <http://www.w3.org/2000/01/rdf-schema#domain> <http://www.semanticschool.com/rdfs#Czlowiek> .

<http://www.semanticschool.com/rdfs#prowadzi> <http://www.w3.org/2000/01/rdf-schema#range> <http://www.semanticschool.com/rdfs#Samochod> .

<http://www.semanticschool.com/data#Jan> <http://www.semanticschool.com/rdfs#prowadzi> <http://www.semanticschool.com/data#Mazda> .

<http://www.semanticschool.com/rdfs#Samochod> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> .

<http://www.semanticschool.com/rdfs#Czlowiek> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2000/01/rdf-schema#Class> .

A teraz czas na wnioskowanie w akcji. Dzięki bibliotece Jena uruchomienie wnioskowania jest bardzo proste.

Musimy najpierw stworzyć nowy model bazujący na poprzednim. Tym razem, nasz model będzie dedykowany dla wnioskowania z RDF Schema.

InfModel infmodel = ModelFactory.createRDFSModel(model);

Podobnie jak poprzednio dodajemy nasze przykładowe zdanie:

Resource rJan = infmodel.createResource(NS_DATA+"Jan");

Resource rMazda = infmodel.createResource(NS_DATA+"Mazda");

rJan.addProperty(pKierowac, rMazda);

Ponieważ cały model infmodel zawiera również trójki związane ze specyfikacją języka ontologii RDF Schema, więc odpytajmy nasz model tylko o typy zasobów [Jan] i [Mazda].

System.out.println(rJan.getProperty(RDF.type));

System.out.println(rMazda.getProperty(RDF.type));

W wyniku otrzymamy:

[http://www.semanticschool.com/data#Jan, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.semanticschool.com/rdfs#Czlowiek]

[http://www.semanticschool.com/data#Mazda, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.semanticschool.com/rdfs#Samochod]

Co tym samym kończy nasz dowód: maszyna wnioskująca poprawnie określiła typ zasobów [Jan] i [Mazda].

Pełen kod projektu razem z biblioteką Jena, znajdziecie [tutaj]