Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:miw:miw08_ruleruntimej [2008/05/30 09:11] miw |
pl:miw:miw08_ruleruntimej [2008/06/14 10:52] gjn |
====== Opis ====== | |
Realizujący: | |
**Marcin Gadamer** <marcin.gadamer@gmail.com> | |
| |
Investigate runtime integration aspects, mainly | |
Prolog+Java integration possibilities | |
* input | |
* Prolog/Java APIs | |
* JSR94 | |
* Jess | |
* JenaRules | |
* integration | |
* output | |
How to integrate Prolog and Java in the best way regarding performance, and coding easiness + examples. | |
[[pl:miw:miw2008_tematy#ruleruntimej|MIW temat]] | |
| |
====== Projekt ====== | |
* "implementacja" jsr94 w prologu | |
* możliwość/sensowność jess/prolog | |
| |
===== Jena wstęp na przykładzie rodziny===== | |
| |
Ponieważ Jess można używać jedynie przez 30 dni, wykorzystuję do integracji framework Jena. | |
| |
* Jednym z zalet Jeny jest czytanie/zapisywanie RDF w RDF/XML, N3 oraz N-Triples. Stąd słuszne wydaje się podejście | |
Prolog <-przedstawienie wiedzy-> RDF <-przedstawienie wiedzy-> Java | |
| |
* Mały program w Java, który pokazuje relacje pomiędzy tatą (Jan), mamą (Krystyna), córką (Kasia), synem (Jasiu) | |
| |
Zostały zapisane następujące dane: | |
corka.addProperty(siostra, syn); | |
tata.addProperty(ojciec, corka); | |
tata.addProperty(ojciec, syn); | |
tata.addProperty(malzonek, mama); | |
mama.addProperty(malzonek, tata); | |
Statement statement1 = model.createStatement(syn, dziecko, mama); | |
Statement statement2 = model.createStatement(syn, dziecko, tata); | |
Statement statement3 = model.createStatement(corka, dziecko, mama); | |
Statement statement4 = model.createStatement(corka, dziecko, tata); | |
| |
W pliku RDF: | |
<code xml> | |
<rdf:RDF | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
xmlns:j.0="http://purl.org/vocab/relacje/" > | |
<rdf:Description rdf:about="http://Family/KowalskiJan"> | |
<j.0:malzonek rdf:resource="http://Family/KowalskiKrystyna"/> | |
<j.0:ojciec rdf:resource="http://Family/KowalskiJasiu"/> | |
<j.0:ojciec rdf:resource="http://Family/KowalskiKasia"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Family/KowalskiKrystyna"> | |
<j.0:malzonek rdf:resource="http://Family/KowalskiJan"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Family/KowalskiKasia"> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiJan"/> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiKrystyna"/> | |
<j.0:siostra rdf:resource="http://Family/KowalskiJasiu"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Family/KowalskiJasiu"> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiJan"/> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiKrystyna"/> | |
</rdf:Description> | |
</rdf:RDF> | |
</code> | |
Przekazany RDF do Javy daje model z zawartością 9 informacji. | |
| |
Po zadaniu prostych zapytań | |
| |
syn.listProperties(dziecko); | |
corka.listProperties(dziecko); | |
corka.listProperties(siostra); | |
otrzymałem: | |
| |
http://Family/KowalskiJasiu jest dzieckiem | |
http://Family/KowalskiJan | |
http://Family/KowalskiKrystyna | |
http://Family/KowalskiKasia jest dzieckiem | |
http://Family/KowalskiJan | |
http://Family/KowalskiKrystyna | |
http://Family/KowalskiKasia ma rodzenstwo | |
http://Family/KowalskiJasiu | |
| |
=====SPARQL===== | |
Zapytania buduje się podobnie jak w języku zapytań SQL z tą różnicą, że podaje się całą trójkę. | |
Zapytanie SPARQL dla podanego powyżej przykładu może wyglądać tak: | |
| |
<code> | |
SELECT ?x ?w ?q | |
WHERE {?x ?w ?q} | |
</code> | |
Oznacza to podgląd całej wiedzy, która jest zawarta w modelu. | |
| |
Na takie zapytanie uzyskałem taką odpowiedź: | |
<code> | |
Jasiu dziecko Jan | |
Jasiu dziecko Krystyna | |
Krystyna malzonek Jan | |
Jan malzonek Krystyna | |
Jan ojciec Jasiu | |
Jan ojciec Kasia | |
Kasia dziecko Jan | |
Kasia dziecko Krystyna | |
Kasia siostra Jasiu | |
</code> | |
| |
Jak widać są to wszytkie informacje, które zawarłem w modelu. (Dla czytelności zostały usunięte URI, aby odpowiedź nie wygdlądała np. tak http://Family/KowalskiJan) | |
| |
Znając zasadę tworzenia zapytania, można otrzymać odpowiedź na "skomplikowane" zapytanie. | |
| |
| |
=====Termostat - RDF===== | |
| |
Aby stworzyć plik RDF reprezentujący model termostatu, najpierw utworzyłem model termostatu wg. reguł. | |
| |
Aby plik taki został wygenerowany ścieżki do resoure'ów oraz propertis'ów muszą być unikalne stąd musiałem stworzyć dwa Stringi, którymi poprzedzałem każdy z nich. | |
<code> | |
static final String resourceUri = "http://Resource/my/"; | |
static final String propertyUri = "http://Property/my/"; | |
</code> | |
| |
| |
Tak zapisałem model w Javie: | |
<code> | |
Model model = ModelFactory.createDefaultModel(); | |
//1 | |
Resource day = model.createResource(resourceUri+ "Day"); | |
Resource workday = model.createResource(resourceUri+"Workday"); | |
Property monday = model.createProperty(propertyUri+"monday"); | |
Property tuesday = model.createProperty(propertyUri+"tuesday"); | |
Property wednesday = model.createProperty(propertyUri+"wednesday"); | |
Property thursday = model.createProperty(propertyUri+"thursday"); | |
Property friday = model.createProperty(propertyUri+"friday"); | |
day.addProperty(monday, workday); | |
day.addProperty(tuesday, workday); | |
day.addProperty(wednesday, workday); | |
day.addProperty(thursday, workday); | |
day.addProperty(friday, workday); | |
| |
//2 | |
Resource weekend = model.createResource(resourceUri + "Weekend"); | |
Property saturday = model.createProperty(propertyUri + "saturday"); | |
Property sunday = model.createProperty(propertyUri+ "sunday"); | |
day.addProperty(saturday, weekend); | |
day.addProperty(sunday, weekend); | |
| |
//3 4 5 | |
Resource time = model.createResource(resourceUri + "time"); | |
Resource hour = model.createResource(resourceUri + "hour"); | |
Property sevenAm = model.createProperty(propertyUri + "seven-before9am"); | |
Property sixPm = model.createProperty(propertyUri + "six-after5pm"); | |
Property noon = model.createProperty(propertyUri + "noon"); | |
time.addProperty(sevenAm, hour); | |
time.addProperty(sixPm, hour); | |
time.addProperty(noon, hour); | |
| |
//6 | |
//-- | |
| |
//7 | |
Resource month = model.createResource(resourceUri+ "month"); | |
Resource summer = model.createResource(resourceUri+"summer"); | |
Property january = model.createProperty(propertyUri+"january"); | |
Property february = model.createProperty(propertyUri+"february"); | |
Property december = model.createProperty(propertyUri+"december"); | |
month.addProperty(january, summer); | |
month.addProperty(february, summer); | |
month.addProperty(december, summer); | |
| |
//8 | |
Resource autumn = model.createResource(resourceUri+"autumn"); | |
Property march = model.createProperty(propertyUri+"march"); | |
Property april = model.createProperty(propertyUri+"april"); | |
Property may = model.createProperty(propertyUri+"may"); | |
month.addProperty(march, autumn); | |
month.addProperty(april, autumn); | |
month.addProperty(may, autumn); | |
| |
//9 | |
Resource winter = model.createResource(resourceUri+"winter"); | |
Property june = model.createProperty(propertyUri+"june"); | |
Property july = model.createProperty(propertyUri+"july"); | |
Property august = model.createProperty(propertyUri+"august"); | |
month.addProperty(june, winter); | |
month.addProperty(july, winter); | |
month.addProperty(august, winter); | |
| |
//10 | |
Resource spring = model.createResource(resourceUri+"spring"); | |
Property september = model.createProperty(propertyUri+"september"); | |
Property october = model.createProperty(propertyUri+"october"); | |
Property november = model.createProperty(propertyUri+"november"); | |
month.addProperty(september, spring); | |
month.addProperty(october, spring); | |
month.addProperty(november, spring); | |
| |
//11 12 13 | |
| |
| |
| |
Resource operation = model.createResource(resourceUri + "operation"); | |
Property businessHours = model.createProperty(propertyUri + "businessHours"); | |
Property notBusinessHours = model.createProperty(propertyUri + "notBusinessHours"); | |
operation.addProperty(businessHours, hour); | |
operation.addProperty(notBusinessHours, hour); | |
| |
//14 15 16 17 18 | |
Resource thermostat = model.createResource(resourceUri + "thermostat"); | |
Resource setting = model.createResource(resourceUri + "setting"); | |
Property degrees20 = model.createProperty(propertyUri + "20degrees"); | |
Property degrees15 = model.createProperty(propertyUri + "15degrees"); | |
Property degrees24 = model.createProperty(propertyUri + "24degrees"); | |
Property degrees27 = model.createProperty(propertyUri + "27degrees"); | |
Property degrees16 = model.createProperty(propertyUri + "16degrees"); | |
Property degrees18 = model.createProperty(propertyUri + "18degrees"); | |
Property degrees14 = model.createProperty(propertyUri + "14degrees"); | |
thermostat.addProperty(degrees20, setting); | |
thermostat.addProperty(degrees15, setting); | |
thermostat.addProperty(degrees24, setting); | |
thermostat.addProperty(degrees27, setting); | |
thermostat.addProperty(degrees16, setting); | |
thermostat.addProperty(degrees18, setting); | |
thermostat.addProperty(degrees14, setting); | |
</code> | |
| |
Na tej podstawie wygenerowałem plik RDF z zapisanym modelem: | |
<code xml> | |
<rdf:RDF | |
xmlns:j.0="http://Property/my/18" | |
xmlns:j.1="http://Property/my/" | |
xmlns:j.2="http://Property/my/15" | |
xmlns:j.3="http://Property/my/24" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
xmlns:j.4="http://Property/my/27" | |
xmlns:j.5="http://Property/my/16" | |
xmlns:j.7="http://Property/my/14" | |
xmlns:j.6="http://Property/my/20" > | |
<rdf:Description rdf:about="http://Resource/my/time"> | |
<j.1:noon rdf:resource="http://Resource/my/hour"/> | |
<j.1:six-after5pm rdf:resource="http://Resource/my/hour"/> | |
<j.1:seven-before9am rdf:resource="http://Resource/my/hour"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/month"> | |
<j.1:january rdf:resource="http://Resource/my/summer"/> | |
<j.1:february rdf:resource="http://Resource/my/summer"/> | |
<j.1:september rdf:resource="http://Resource/my/spring"/> | |
<j.1:october rdf:resource="http://Resource/my/spring"/> | |
<j.1:july rdf:resource="http://Resource/my/winter"/> | |
<j.1:november rdf:resource="http://Resource/my/spring"/> | |
<j.1:may rdf:resource="http://Resource/my/autumn"/> | |
<j.1:april rdf:resource="http://Resource/my/autumn"/> | |
<j.1:august rdf:resource="http://Resource/my/winter"/> | |
<j.1:june rdf:resource="http://Resource/my/winter"/> | |
<j.1:december rdf:resource="http://Resource/my/summer"/> | |
<j.1:march rdf:resource="http://Resource/my/autumn"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/Day"> | |
<j.1:sunday rdf:resource="http://Resource/my/Weekend"/> | |
<j.1:saturday rdf:resource="http://Resource/my/Weekend"/> | |
<j.1:friday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:thursday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:wednesday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:tuesday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:monday rdf:resource="http://Resource/my/Workday"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/operation"> | |
<j.1:notBusinessHours rdf:resource="http://Resource/my/hour"/> | |
<j.1:businessHours rdf:resource="http://Resource/my/hour"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/thermostat"> | |
<j.7:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.0:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.5:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.4:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.3:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.2:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.6:degrees rdf:resource="http://Resource/my/setting"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
</code> | |
| |
| |
| |
| |
| |
| |
===== Przykład programu wnioskującego (Java+Jena) ===== | |
| |
W tej części przedstawię program, który na podstawie danych wejściowych nastawia temperaturę. Program został napisany w oparciu o reguły dla [[hekate:hekate_case_thermostat|termostatu]]. | |
| |
Jako dane wejściowe od użytkownika pobierane są następujące informacje: | |
* miesiąc | |
* dzień | |
* godzina | |
| |
W przyszłości dane te będą mogły być pobierane automatycznie na podstawie aktualnej daty w systemie. Dzięki tak pobieranej informacji będzie możliwe sterowanie temperaturą "prawie" w czasie rzeczywistym. Ze względu na przeprowadzane testy, dane na tym etapie są wpisane w kodzie programu. | |
| |
===Opis programu=== | |
| |
**Założenia:** | |
| |
Program na podstawie pobieranych danych (miesiąc, dzień, godzina) potrafi poprzez zapisane reguły oraz system wnioskowania ustalić temperaturę termostatu. | |
| |
**Implementacja:** | |
* W pierwszej kolejności wpisywane są dane przez użytkownika | |
<code java> | |
//data to run rules | |
String day = "monday"; | |
String hour = "h11"; | |
String month = "july"; | |
</code> | |
| |
* Następnie tworzony jest model (na którym będziemy przeprowadzać wnioskowanie). Ponieważ musimy uwzględnić podane wcześniej informacje, dodajemy je (i tylko je) do modelu. | |
<code java> | |
//creating new model | |
Model model = ModelFactory.createDefaultModel(); | |
// creating day | |
Resource dayResource = model.createResource(baseURI + "day"); | |
Property dayProperty = model.createProperty(baseURI + day); | |
dayResource.addProperty(dayProperty, dayResource); | |
// creating time | |
Resource hourResource = model.createResource(baseURI + "hour"); | |
Property hourProperty = model.createProperty(baseURI + hour); | |
hourResource.addProperty(hourProperty, hourResource); | |
// creating month | |
Resource monthResource = model.createResource(baseURI + "month"); | |
Property monthProperty = model.createProperty(baseURI + month); | |
monthResource.addProperty(monthProperty, monthResource); | |
</code> | |
| |
* Gdy mamy utworzony model musimy zapisać reguły. Użyłem w projekcie ponad 50 reguł, aby móc opisać dokładnie zasadę działania podanego powyżej termostatu. W tym miejscu zapiszę zaledwie ważniejsze reguły. Wszystkie reguły można zobaczyć w kodzie programu. | |
<code java> | |
//day: | |
String ruleSrc = " [ruleD1: (?a http://uri#monday ?b) -> (?a http://uri#monday http://uri#workday)]" | |
+ " [ruleD7: (?a http://uri#sunday ?b) -> (?a http://uri#sunday http://uri#weekend)]" | |
| |
// time: between 9 am and 5 pm | |
+ " [ruleT10: (?x http://uri#h10 ?h) -> (?x http://uri#h10 http://uri#beetwen)]" | |
| |
// time: before 9 am and after 5 pm | |
+ " [ruleT17: (?x http://uri#h17 ?h) -> (?x http://uri#h17 http://uri#out)]" | |
| |
// getting day and hour | |
+ " [ruleGDH1: (?gdh1gd http://uri#" + day + " http://uri#workday),(?gdh1gh http://uri#" + hour + " http://uri#beetwen) -> (http://uri#operation http://uri#mode http://uri#during)]" | |
| |
//months: | |
+ " [ruleS1: (?s1s1 http://uri#january ?s1s2) -> (?s1s1 http://uri#january http://uri#summer)]" | |
+ " [ruleS3: (?s3s1 http://uri#march ?s3s2) -> (?s3s1 http://uri#march http://uri#autumn)]" | |
| |
//getting month and operation | |
+ " [ruleGMO1: (?gmo1gm http://uri#" + month + " http://uri#spring),(?gmo1go http://uri#mode http://uri#during) -> (http://uri#temperature http://uri#set http://uri#20)]" | |
+ " [ruleGMO2: (?gmo2gm http://uri#" + month + " http://uri#spring),(?gmo2go http://uri#mode http://uri#notDuring) -> (http://uri#temperature http://uri#set http://uri#15)]" | |
</code> | |
| |
* Po utworzeniu modelu oraz reguł musimy uruchomić mechanizm wnioskujący. W tym celu należy wpisać | |
<code java> | |
List rules = Rule.parseRules(ruleSrc); | |
Reasoner reasoner = new GenericRuleReasoner(rules); | |
InfModel inf = ModelFactory.createInfModel(reasoner, model); | |
inf.getDeductionsModel().write(System.out); | |
</code> | |
| |
* W celu pokazania powstałego modelu poprzez etap wnioskowania i zapisania go w postaci "trójek" należy wpisać | |
<code java> | |
Iterator list = inf.listStatements(null, null, (RDFNode) null); | |
while (list.hasNext()) { | |
System.out.println(" - " + list.next()); | |
} | |
</code> | |
| |
**Źródła:** | |
| |
Z braku możliwości zamieszczenia pliku z rozszerzeniem .java zamieszczam plik .txt (proszę o ściągnięcie pliku na dysk i zminie rozszerzenia) | |
{{:pl:miw:miw08_ruleruntimej:jenarulesengine.txt|JenaRulesEngine.txt}} | |
| |
W celu uruchomienia aplikacji należy dodać biblioteki frameworka Jena. Źródła można pobrać ze strony [[http://sourceforge.net/project/downloading.php?groupname=jena&filename=Jena-2.5.5.zip&use_mirror=switch | link]] | |
Osobiście korzystałem z wersji frameworka //Jena-2.5.5// | |
| |
| |
**Przykład działania:** | |
* Uruchomienie nr 1 | |
<code> | |
>>> Start Jena Rules <<< | |
Data: | |
day: monday hour: h11 month: july | |
| |
| |
| |
Created model (RDF): | |
<rdf:RDF | |
xmlns:j.0="http://uri#" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > | |
<rdf:Description rdf:about="http://uri#day"> | |
<j.0:monday rdf:resource="http://uri#day"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#month"> | |
<j.0:july rdf:resource="http://uri#month"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#hour"> | |
<j.0:h11 rdf:resource="http://uri#hour"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
| |
| |
Deduction model (RDF): | |
<rdf:RDF | |
xmlns:j.0="http://uri#" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > | |
<rdf:Description rdf:about="http://uri#day"> | |
<j.0:monday rdf:resource="http://uri#workday"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#month"> | |
<j.0:july rdf:resource="http://uri#winter"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#hour"> | |
<j.0:h11 rdf:resource="http://uri#beetwen"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#temperature"> | |
<j.0:set rdf:resource="http://uri#18"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#operation"> | |
<j.0:mode rdf:resource="http://uri#during"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
| |
| |
Deduction model presented in N3: | |
- [http://uri#temperature, http://uri#set, http://uri#18] | |
- [http://uri#hour, http://uri#h11, http://uri#beetwen] | |
- [http://uri#operation, http://uri#mode, http://uri#during] | |
- [http://uri#day, http://uri#monday, http://uri#workday] | |
- [http://uri#month, http://uri#july, http://uri#winter] | |
- [http://uri#month, http://uri#july, http://uri#month] | |
- [http://uri#day, http://uri#monday, http://uri#day] | |
- [http://uri#hour, http://uri#h11, http://uri#hour] | |
</code> | |
| |
| |
* Uruchomienie nr 2 | |
<code> | |
| |
>>> Start Jena Rules <<< | |
Data: | |
day: sunday hour: h15 month: october | |
| |
| |
| |
Created model (RDF): | |
<rdf:RDF | |
xmlns:j.0="http://uri#" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > | |
<rdf:Description rdf:about="http://uri#day"> | |
<j.0:sunday rdf:resource="http://uri#day"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#month"> | |
<j.0:october rdf:resource="http://uri#month"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#hour"> | |
<j.0:h15 rdf:resource="http://uri#hour"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
| |
| |
Deduction model (RDF): | |
<rdf:RDF | |
xmlns:j.0="http://uri#" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > | |
<rdf:Description rdf:about="http://uri#day"> | |
<j.0:sunday rdf:resource="http://uri#weekend"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#month"> | |
<j.0:october rdf:resource="http://uri#spring"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#hour"> | |
<j.0:h15 rdf:resource="http://uri#beetwen"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#temperature"> | |
<j.0:set rdf:resource="http://uri#15"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#operation"> | |
<j.0:mode rdf:resource="http://uri#notDuring"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
| |
| |
Deduction model presented in N3: | |
- [http://uri#temperature, http://uri#set, http://uri#15] | |
- [http://uri#hour, http://uri#h15, http://uri#beetwen] | |
- [http://uri#operation, http://uri#mode, http://uri#notDuring] | |
- [http://uri#day, http://uri#sunday, http://uri#weekend] | |
- [http://uri#month, http://uri#october, http://uri#spring] | |
- [http://uri#month, http://uri#october, http://uri#month] | |
- [http://uri#day, http://uri#sunday, http://uri#day] | |
- [http://uri#hour, http://uri#h15, http://uri#hour] | |
</code> | |
| |
| |
* Uruchomienie nr 3 | |
<code> | |
>>> Start Jena Rules <<< | |
Data: | |
day: wednesday hour: h23 month: february | |
| |
| |
| |
Created model (RDF): | |
<rdf:RDF | |
xmlns:j.0="http://uri#" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > | |
<rdf:Description rdf:about="http://uri#day"> | |
<j.0:wednesday rdf:resource="http://uri#day"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#month"> | |
<j.0:february rdf:resource="http://uri#month"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#hour"> | |
<j.0:h23 rdf:resource="http://uri#hour"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
| |
| |
Deduction model (RDF): | |
<rdf:RDF | |
xmlns:j.0="http://uri#" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > | |
<rdf:Description rdf:about="http://uri#day"> | |
<j.0:wednesday rdf:resource="http://uri#workday"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#month"> | |
<j.0:february rdf:resource="http://uri#summer"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#hour"> | |
<j.0:h23 rdf:resource="http://uri#out"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#temperature"> | |
<j.0:set rdf:resource="http://uri#27"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://uri#operation"> | |
<j.0:mode rdf:resource="http://uri#notDuring"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
| |
| |
Deduction model presented in N3: | |
- [http://uri#temperature, http://uri#set, http://uri#27] | |
- [http://uri#hour, http://uri#h23, http://uri#out] | |
- [http://uri#operation, http://uri#mode, http://uri#notDuring] | |
- [http://uri#day, http://uri#wednesday, http://uri#workday] | |
- [http://uri#month, http://uri#february, http://uri#summer] | |
- [http://uri#month, http://uri#february, http://uri#month] | |
- [http://uri#day, http://uri#wednesday, http://uri#day] | |
- [http://uri#hour, http://uri#h23, http://uri#hour] | |
| |
</code> | |
| |
| |
| |
===== Translacja r2ml do reguł Jeny ===== | |
| |
Miałem przeprowadzić translację therm w r2ml do reguł Jeny. | |
| |
W tym celu skorzystałem ze strony [[http://oxygen.informatik.tu-cottbus.de/rewerse-i1/?q=node/15|strona]] a wykorzystałem do tego thermy ze strony [[pl:miw:miw08_xtt_r2ml:thermostat|r2ml]]. | |
| |
Niestety po przekopiowaniu całego tekstu do wspomnianego translatora otrzymałem bład postaci: | |
<code> | |
[ERR0011] org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed. | |
</code> | |
| |
Postanowiłem więc spróbować dla każdej z reguł w r2ml zastosować translator. Dla pierwszej reguły | |
<code xml> | |
<r2ml:RuleBase xmlns:r2ml="http://www.rewerse.net/I1/2006/R2ML" | |
xmlns:r2mlv="http://www.rewerse.net/I1/2006/R2ML/R2MLV" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:xs="http://www.w3.org/2001/XMLSchema" | |
xmlns:userv="http://www.businessrulesforum.com/2005/userv#" | |
xmlns:swrlb="http://www.w3.org/2003/11/swrlb" | |
xsi:schemaLocation="http://oxygen.informatik.tu-cottbus.de/R2ML/0.5/R2ML.xsd"> | |
| |
<r2ml:ProductionRuleSet> | |
<r2ml:ProductionRule r2ml:ruleID="Thermostat01" | |
| |
xmlns:ext="http://borg.ia.agh.edu.pl/~tpalosz/jboss/org.drools.examples.Date"> | |
<r2ml:Documentation> | |
<r2ml:RuleText r2ml:textFormat="plain"> | |
if the day is Monday | |
or the day is Tuesday or the day is Wednesday | |
or the day is Thursday or the day is Friday | |
then today is a workday | |
</r2ml:RuleText> | |
</r2ml:Documentation> | |
<r2ml:conditions> | |
| |
<r2ml:qf.Disjunction> | |
<r2ml:DatatypePredicateAtom r2ml:datatypePredicateID="swrlb:equal"> | |
<r2ml:dataArguments> | |
<r2ml:AttributeFunctionTerm r2ml:attributeID="day"> | |
<r2ml:contextArgument> | |
<r2ml:ObjectVariable r2ml:name="date" r2ml:classID="Date"/> | |
</r2ml:contextArgument> | |
</r2ml:AttributeFunctionTerm> | |
<r2ml:TypedLiteral r2ml:lexicalValue="Monday" r2ml:datatypeID="xs:string"/> | |
</r2ml:dataArguments> | |
</r2ml:DatatypePredicateAtom> | |
| |
<r2ml:DatatypePredicateAtom r2ml:datatypePredicateID="swrlb:equal"> | |
<r2ml:dataArguments> | |
<r2ml:AttributeFunctionTerm r2ml:attributeID="day"> | |
<r2ml:contextArgument> | |
<r2ml:ObjectVariable r2ml:name="date" r2ml:classID="Date"/> | |
</r2ml:contextArgument> | |
</r2ml:AttributeFunctionTerm> | |
<r2ml:TypedLiteral r2ml:lexicalValue="Tuesday" r2ml:datatypeID="xs:string"/> | |
</r2ml:dataArguments> | |
</r2ml:DatatypePredicateAtom> | |
| |
<r2ml:DatatypePredicateAtom r2ml:datatypePredicateID="swrlb:equal"> | |
<r2ml:dataArguments> | |
<r2ml:AttributeFunctionTerm r2ml:attributeID="day"> | |
<r2ml:contextArgument> | |
<r2ml:ObjectVariable r2ml:name="date" r2ml:classID="Date"/> | |
</r2ml:contextArgument> | |
</r2ml:AttributeFunctionTerm> | |
<r2ml:TypedLiteral r2ml:lexicalValue="Wednesday" r2ml:datatypeID="xs:string"/> | |
</r2ml:dataArguments> | |
</r2ml:DatatypePredicateAtom> | |
| |
<r2ml:DatatypePredicateAtom r2ml:datatypePredicateID="swrlb:equal"> | |
<r2ml:dataArguments> | |
<r2ml:AttributeFunctionTerm r2ml:attributeID="day"> | |
<r2ml:contextArgument> | |
<r2ml:ObjectVariable r2ml:name="date" r2ml:classID="Date"/> | |
</r2ml:contextArgument> | |
</r2ml:AttributeFunctionTerm> | |
<r2ml:TypedLiteral r2ml:lexicalValue="Thursday" r2ml:datatypeID="xs:string"/> | |
</r2ml:dataArguments> | |
</r2ml:DatatypePredicateAtom> | |
| |
<r2ml:DatatypePredicateAtom r2ml:datatypePredicateID="swrlb:equal"> | |
<r2ml:dataArguments> | |
<r2ml:AttributeFunctionTerm r2ml:attributeID="day"> | |
<r2ml:contextArgument> | |
<r2ml:ObjectVariable r2ml:name="date" r2ml:classID="Date"/> | |
</r2ml:contextArgument> | |
</r2ml:AttributeFunctionTerm> | |
<r2ml:TypedLiteral r2ml:lexicalValue="Friday" r2ml:datatypeID="xs:string"/> | |
</r2ml:dataArguments> | |
</r2ml:DatatypePredicateAtom> | |
| |
</r2ml:qf.Disjunction> | |
</r2ml:conditions> | |
| |
<r2ml:producedAction> | |
<r2ml:AssignActionExpression r2ml:propertyID="today"> | |
<r2ml:contextArgument> | |
<r2ml:ObjectVariable r2ml:classID="Date" r2ml:name="date" /> | |
</r2ml:contextArgument> | |
<r2ml:value> | |
<r2ml:TypedLiteral r2ml:lexicalValue="workday" r2ml:datatypeID="xs:string"/> | |
</r2ml:value> | |
</r2ml:AssignActionExpression> | |
</r2ml:producedAction> | |
</r2ml:ProductionRule> | |
</r2ml:ProductionRuleSet> | |
| |
</r2ml:RuleBase> | |
</code> | |
| |
Otrzymałem coś takiego | |
<code> | |
r2ml:qf.DisjunctionDisjunction is not supported by Jena Rules ! | |
</code> | |
| |
Taki sam komunikat otrzymałem dla drugiej reguły. | |
| |
| |
Dla trzeciej reguły tłumaczenie się powiodło, jednak wynik tego tłumaczenia jest daleki od spodziewanego. | |
| |
Wygląda on tak | |
<code> | |
<?xml version="1.0" encoding="UTF-8"?> | |
<!--// Jena output of R2ML Derivation Rules and Production Rules--> | |
<jena> | |
| |
| |
<ns xmlns:r2mlv="http://www.rewerse.net/I1/2006/R2ML/R2MLV" | |
xmlns:userv="http://www.businessrulesforum.com/2005/userv#" | |
xmlns:swrlb="http://www.w3.org/2003/11/swrlb" | |
xmlns:xs="http://www.w3.org/2001/XMLSchema" | |
xmlns:r2ml="http://www.rewerse.net/I1/2006/R2ML" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:ext="http://borg.ia.agh.edu.pl/~tpalosz/jboss/org.drools.examples.Date"/> | |
| |
| |
| |
| |
| |
[ () ge( | |
time( | |
?date | |
)) () -> ] | |
| |
| |
| |
| |
| |
| |
</jena> | |
</code> | |
| |
Skontaktowałem się więc z Tomkiem w celu uzyskania jakiejś pomocy. Ustaliliśmy, zresztą zgodnie z komunikatem, że prawdopodobnie translator nie obsługuje Disjunction, które Tomek zastosował. | |
| |
Dla trzeciego tłumaczenia, te które się udało próbowaliśmy więc uzyskać "lepszy" rezultat, jednak zarówno przy zastosowaniu słownika oraz bez niego rezultaty pozostają takie same. Podejrzewamy więc, że stworzone thermy w r2ml'u odbiegają od standardu w jakim działa wspomniany translator. Możliwe jest, że reguły zapisane w r2ml są poprawnie, jednak translator nie potrafi ich przekształcić na właściwy kod Jeny. | |
| |
| |
| |
| |
===== Translacja xttml do reguł Jeny ===== | |
| |
Po zapoznaniu się z formą zapisu reguł w formacie [[hekate:hekate_markup_language#xttml|XTTML]] doszedłem do następujących wniosków: | |
| |
* Mam przedstawić podaną regułę z XTTML w Jenie | |
<code> | |
rule_1: if att_0 in <1,5>u{8} then att_1 = att_0 + 1 and att_1 = 5 + sin(att_0) | |
</code> | |
| |
Mogę w tym celu stworzyć nowy model zgodnie z trójką zasób1<-własność->zasób2 (zasób1,własność,zasob2) oraz na tak stworzonym modelu skorzystać z reguł, które są opisane również jako trójka (a,b,c)->(d,e,f) (jeśli zachodzi taka trójka (a,b,c) to wykonaj na modelu (e,f,g)) Dodatkowo jest możliwość w zapisie reguł określenia ilości czynników jakie muszą zajść, żeby wykonać operację na modelu. | |
* Reguły w Jenie powinny być zapisane "nie matematycznie" tzn Jena posiada jedynie kilka "prymitywnych funkcji wbudowanych" natomiast bardziej skomplikowane operacje (takie jak sinus nie są uwzględniane). Na [[http://jena.sourceforge.net/inference/|stronie]] można zobaczyć, jakie funkcje są wbudowane. Do tego konkretnego przykładu pomocne będą | |
<code> | |
lessThan(?x, ?y) | |
greaterThan(?x, ?y) | |
le(?x, ?y), ge(?x, ?y) | |
| |
Test if x is <, >, <= or >= y. Only passes if both x and y are numbers or time instants (can be integer or floating point or XSDDateTime). | |
| |
| |
sum(?a, ?b, ?c) | |
addOne(?a, ?c) | |
difference(?a, ?b, ?c) | |
min(?a, ?b, ?c) | |
max(?a, ?b, ?c) | |
product(?a, ?b, ?c) | |
quotient(?a, ?b, ?c) | |
| |
Sets c to be (a+b), (a+1) (a-b), min(a,b), max(a,b), (a*b), (a/b). Note that these do not run backwards, if in sum a and c are bound and b is unbound then the test will fail rather than bind b to (c-a). This could be fixed. | |
</code> | |
| |
* Można więc zapisać, że na modelu ma się coś wykonać (operacja po słowie then) gdy **lessThan(att_0, 5)** oraz **greaterThan(att_0, 1)** [ lessThan(att_0, 5),greaterThan(att_0, 1)->.....] | |
| |
* Operacje na modelu //att_1 = att_0 + 1// and //att_1 = 5 + sin(att_0)// zapiszemy po -> jako dwa osobne działania. Pierwsze z nich //att_1 = att_0 + 1// możemy zapisać ponownie wykorzystując funkcje Jeny **sum(att_0, 1, att_1)**. Drugie działanie //att_1 = 5 + sin(att_0)// już tak prosto nie da się wykonać ponieważ brak jest odpowiedniej funkcji do obliczania sinusa. Jednak zapytanie powinno wyglądać podobnie do tego **sum(5, sin(att_0), att_1)** | |
| |
* Można więc ostatecznie zapisać podaną regułę jako String w postaci | |
<code> | |
String str = "rule1: lessThan(att_0, 5),greaterThan(att_0, 1)-> sum(att_0, 1, att_1),sum(5, sin(att_0), att_1)"; | |
</code> | |
| |
| |
* Uważam, że uzyskanie takich informacji z wskazanych wcześniej reguł w formacie [[hekate:hekate_markup_language#xttml|XTTML]] będzie bardzo trudnym zadaniem. | |
Jednak wydaje się, że dla reguł "niematematycznych" w formacie XTTML możliwe jest zbudowanie dość prostego parsera, który wyciągnie odpowiednie dane z XTTML i przekaże do metody napisanej w języku Java, która to utworzy reguły dla Jeny. | |
Ponieważ reguły zapisywane są jako jeden String, można stworzyć metodę, która będzie tworzyć jedynie jedną trójkę (a,b,c), natomiast sam algorytm wskaże w które miejsce umieścić znak -> i wpisać operacje na modelu. Przez wielokrotne wywołanie wcześniejszej metody powinniśmy uzyskać podobny efekt. Jednak tak stworzone reguły powinny mieć jak najprostszą postać czyli (a1,a2,a3),(b1,b2,b3)->(c1,c2,c3) | |
| |
| |
| |
| |
| |
====== Sprawozdanie ====== | |
| |
| |
===== What is Jena ===== | |
Jena is a Java framework for building Semantic Web applications. It provides a programmatic environment for RDF, RDFS and OWL, SPARQL and includes a rule-based inference engine. | |
| |
Jena is open source and grown out of work with the HP Labs Semantic Web Programme. | |
| |
The Jena Framework includes: | |
* A RDF API | |
* Reading and writing RDF in RDF/XML, N3 and N-Triples | |
* An OWL API | |
* In-memory and persistent storage | |
* SPARQL query engine | |
| |
| |
[[http://jena.sourceforge.net/ | Źródło]] | |
| |
| |
===== RDF ===== | |
The Resource Description Framework (RDF) is a standard (technically a W3C Recommendation) for describing resources. Resource is anything we can identify. | |
| |
RDF is best thought of in the form of node. | |
| |
**Resources have properties**. The name of resources and properties are also a URI, but as URI's are rather long and cumbersome, the diagram shows it in XML qname form. The part before the ':' is called a namespace prefix and represents a namespace. The part after the ':' is called a local name and represents a name in that namespace. Properties are usually represented in this qname form when written as RDF XML and it is a convenient shorthand for representing them in diagrams and in text. Strictly, however, properties are identified by a URI. The nsprefix:localname form is a shorthand for the URI of the namespace concatenated with the localname. There is no requirement that the URI of a property resolve to anything when accessed by a browser. | |
| |
Each **property has a value**. | |
| |
| |
[[http://jena.sourceforge.net/tutorial/RDF_API/index.html | Źródło]] | |
| |
| |
===== Building model in Jena ===== | |
| |
Jena is a Java API which can be used to create and manipulate RDF graphs. Jena has object classes to represent graphs, resources, properties and literals. The interfaces representing resources, properties and literals are called Resource, Property and Literal respectively. In Jena, a graph is called a model and is represented by the Model interface. | |
| |
The code to create a graph, or model, is simple: | |
<code java> | |
// some definitions | |
static String personURI = "http://somewhere/JohnSmith"; | |
static String fullName = "John Smith"; | |
| |
// create an empty Model | |
Model model = ModelFactory.createDefaultModel(); | |
| |
// create the resource | |
Resource johnSmith = model.createResource(personURI); | |
| |
// add the property | |
johnSmith.addProperty(VCARD.FN, fullName); | |
</code> | |
It begins with some constant definitions and then creates an empty Model or model, using the ModelFactory method createDefaultModel() to create a memory-based model. Jena contains other implementations of the Model interface, e.g one which uses a relational database: these types of Model are also available from ModelFactory. | |
| |
The John Smith resource is then created and a property added to it. The property is provided by a "constant" class VCARD which holds objects representing all the definitions in the VCARD schema. Jena provides constant classes for other well known schemas, such as RDF and RDF schema themselves, Dublin Core and DAML. | |
| |
The code to create the resource and add the property, can be more compactly written in a cascading style: | |
<code java> | |
Resource johnSmith = | |
model.createResource(personURI) | |
.addProperty(VCARD.FN, fullName); | |
</code> | |
| |
| |
Now let's add some more detail to the vcard, exploring some more features of RDF and Jena. | |
| |
| |
| |
RDF properties can also take other resources as their value. | |
| |
Let's add a new property, vcard:N, to represent the structure of John Smith's name. There are several things of interest about this Model. Note that the vcard:N property takes a resource as its value. Note also that the ellipse representing the compound name has no URI. It is known as an blank Node. | |
| |
The Jena code to construct this example, is again very simple. First some declarations and the creation of the empty model. | |
<code java> | |
// some definitions | |
String personURI = "http://somewhere/JohnSmith"; | |
String givenName = "John"; | |
String familyName = "Smith"; | |
String fullName = givenName + " " + familyName; | |
| |
// create an empty Model | |
Model model = ModelFactory.createDefaultModel(); | |
| |
// create the resource | |
// and add the properties cascading style | |
Resource johnSmith | |
= model.createResource(personURI) | |
.addProperty(VCARD.FN, fullName) | |
.addProperty(VCARD.N, | |
model.createResource() | |
.addProperty(VCARD.Given, givenName) | |
.addProperty(VCARD.Family, familyName)); | |
</code> | |
| |
| |
[[http://jena.sourceforge.net/tutorial/RDF_API/index.html | Źródło]] | |
| |
| |
| |
===== Overview of the rule engine(s) ===== | |
| |
Jena2 includes a general purpose rule-based reasoner which is used to implement both the RDFS and OWL reasoners but is also available for general use. This reasoner supports rule-based inference over RDF graphs and provides forward chaining, backward chaining and a hybrid execution model. To be more exact, there are two internal rule engines one forward chaining RETE engine and one tabled datalog engine - they can be run separately or the forward engine can be used to prime the backward engine which in turn will be used to answer queries. | |
| |
The various engine configurations are all accessible through a single parameterized reasoner GenericRuleReasoner. At a minimum a GenericRuleReasoner requires a ruleset to define its behaviour. A GenericRuleReasoner instance with a ruleset can be used like any of the other reasoners described above - that is it can be bound to a data model and used to answer queries to the resulting inference model. | |
| |
The rule reasoner can also be extended by registering new procedural primitives. The current release includes a starting set of primitives which are sufficient for the RDFS and OWL implementations but is easily extensible. | |
| |
| |
[[http://jena.sourceforge.net/inference/#rules | Źródło]] | |
| |
| |
| |
===== Rule syntax and structure ===== | |
| |
| |
A rule for the rule-based reasoner is defined by a Java Rule object with a list of body terms (premises), a list of head terms (conclusions) and an optional name and optional direction. Each term or ClauseEntry is either a triple pattern, an extended triple pattern or a call to a builtin primitive. A rule set is simply a List of Rules. | |
| |
For convenience a rather simple parser is included with Rule which allows rules to be specified in reasonably compact form in text source files. However, it would be perfectly possible to define alternative parsers which handle rules encoded using, say, XML or RDF and generate Rule objects as output. It would also be possible to build a real parser for the current text file syntax which offered better error recovery and diagnostics. | |
| |
An informal description of the simplified text rule syntax is: | |
<code> | |
Rule := bare-rule . | |
or [ bare-rule ] | |
or [ ruleName : bare-rule ] | |
| |
bare-rule := term, ... term -> hterm, ... hterm // forward rule | |
or term, ... term <- term, ... term // backward rule | |
| |
hterm := term | |
or [ bare-rule ] | |
| |
term := (node, node, node) // triple pattern | |
or (node, node, functor) // extended triple pattern | |
or builtin(node, ... node) // invoke procedural primitive | |
| |
functor := functorName(node, ... node) // structured literal | |
| |
node := uri-ref // e.g. http://foo.com/eg | |
or prefix:localname // e.g. rdf:type | |
or <uri-ref> // e.g. <myscheme:myuri> | |
or ?varname // variable | |
or 'a literal' // a plain string literal | |
or 'lex'^^typeURI // a typed literal, xsd:* type names supported | |
or number // e.g. 42 or 25.5 | |
</code> | |
The "," separators are optional. | |
| |
The difference between the forward and backward rule syntax is only relevant for the hybrid execution strategy, see below. | |
| |
The functor in an extended triple pattern is used to create and access structured literal values. The functorName can be any simple identifier and is not related to the execution of builtin procedural primitives, it is just a datastructure. It is useful when a single semantic structure is defined across multiple triples and allows a rule to collect those triples together in one place. | |
| |
To keep rules readable qname syntax is supported for URI refs. The set of known prefixes is those registered with the PrintUtil object. This initially knows about rdf, rdfs, owl, daml, xsd and a test namespace eg, but more mappings can be registered in java code. In addition it is possible to define additional prefix mappings in the rule file, see below. | |
| |
Here are some example rules which illustrate most of these constructs: | |
<code> | |
[allID: (?C rdf:type owl:Restriction), (?C owl:onProperty ?P), | |
(?C owl:allValuesFrom ?D) -> (?C owl:equivalentClass all(?P, ?D)) ] | |
| |
[all2: (?C rdfs:subClassOf all(?P, ?D)) -> print('Rule for ', ?C) | |
[all1b: (?Y rdf:type ?D) <- (?X ?P ?Y), (?X rdf:type ?C) ] ] | |
| |
[max1: (?A rdf:type max(?P, 1)), (?A ?P ?B), (?A ?P ?C) | |
-> (?B owl:sameAs ?C) ] | |
</code> | |
Rule allID illustrates the functor use for collecting the components of an OWL restriction into a single datastructure which can then fire further rules. Rule all2 illustrates a forward rule which creates a new backward rule and also calls the print procedural primitive. Rule max1 illustrates use of numeric literals. | |
| |
Rule files may be loaded and parsed using: | |
<code> | |
List rules = Rule.rulesFromURL("file:myfile.rules"); | |
</code> | |
or | |
<code> | |
BufferedReader br = /* open reader */ ; | |
List rules = Rule.parseRules( Rule.rulesParserFromReader(br) ); | |
</code> | |
| |
or | |
<code> | |
String ruleSrc = /* list of rules in line */ | |
List rules = Rule.parseRules( rulesSrc ); | |
</code> | |
| |
In the first two cases (reading from a URL or a BufferedReader) the rule file is preprocessed by a simple processor which strips comments and supports some additional macro commands: | |
| |
# ... | |
A comment line. | |
// ... | |
A comment line. | |
| |
| |
@prefix pre: <http://domain/url#>. | |
Defines a prefix pre which can be used in the rules. The prefix is local to the rule file. | |
| |
@include <urlToRuleFile>. | |
Includes the rules defined in the given file in this file. The included rules will appear before the user defined rules, irrespective of where in the file the @include directive appears. A set of special cases is supported to allow a rule file to include the predefined rules for RDFS and OWL - in place of a real URL for a rule file use one of the keywords RDFS OWL OWLMicro OWLMini (case insensitive). | |
| |
So an example complete rule file which includes the RDFS rules and defines a single extra rule is: | |
<code> | |
# Example rule file | |
@prefix pre: <http://jena.hpl.hp.com/prefix#>. | |
@include <RDFS>. | |
| |
[rule1: (?f pre:father ?a) (?u pre:brother ?f) -> (?u pre:uncle ?a)] | |
</code> | |
| |
[[http://jena.sourceforge.net/inference/#rules | Źródło]] | |
| |
| |
| |
===== Model rodziny ===== | |
| |
Pierwszy model jaki utworzyłem w Javie z wykorzystaniem frameworku Jena był model rodziny. Pokazywał on proste relacje pomiędzy tatą (Jan), mamą (Krystyna), córką (Kasia), synem (Jasiu) | |
| |
Zostały zapisane następujące dane: | |
corka.addProperty(siostra, syn); | |
tata.addProperty(ojciec, corka); | |
tata.addProperty(ojciec, syn); | |
tata.addProperty(malzonek, mama); | |
mama.addProperty(malzonek, tata); | |
Statement statement1 = model.createStatement(syn, dziecko, mama); | |
Statement statement2 = model.createStatement(syn, dziecko, tata); | |
Statement statement3 = model.createStatement(corka, dziecko, mama); | |
Statement statement4 = model.createStatement(corka, dziecko, tata); | |
| |
W pliku RDF: | |
<code xml> | |
<rdf:RDF | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
xmlns:j.0="http://purl.org/vocab/relacje/" > | |
<rdf:Description rdf:about="http://Family/KowalskiJan"> | |
<j.0:malzonek rdf:resource="http://Family/KowalskiKrystyna"/> | |
<j.0:ojciec rdf:resource="http://Family/KowalskiJasiu"/> | |
<j.0:ojciec rdf:resource="http://Family/KowalskiKasia"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Family/KowalskiKrystyna"> | |
<j.0:malzonek rdf:resource="http://Family/KowalskiJan"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Family/KowalskiKasia"> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiJan"/> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiKrystyna"/> | |
<j.0:siostra rdf:resource="http://Family/KowalskiJasiu"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Family/KowalskiJasiu"> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiJan"/> | |
<j.0:dziecko rdf:resource="http://Family/KowalskiKrystyna"/> | |
</rdf:Description> | |
</rdf:RDF> | |
</code> | |
Przekazany RDF do Javy daje model z zawartością 9 informacji. | |
| |
Po zadaniu prostych zapytań | |
| |
syn.listProperties(dziecko); | |
corka.listProperties(dziecko); | |
corka.listProperties(siostra); | |
otrzymałem: | |
| |
http://Family/KowalskiJasiu jest dzieckiem | |
http://Family/KowalskiJan | |
http://Family/KowalskiKrystyna | |
http://Family/KowalskiKasia jest dzieckiem | |
http://Family/KowalskiJan | |
http://Family/KowalskiKrystyna | |
http://Family/KowalskiKasia ma rodzenstwo | |
http://Family/KowalskiJasiu | |
| |
| |
| |
===== SPARQL ===== | |
| |
Następnym etapem mojej pracy było poznanie reguł budowania zapytań językiem SPARQL. | |
| |
SPARQL (ang. SPARQL Protocol And RDF Query Language) jest językiem zapytań i protokołem dla plików RDF. SPARQL pozwala wyciągać z nich dane zawężone według kryteriów określonych poprzez predykaty RDF. Jest opisany przez kilka specyfikacji W3C. W tej chwili wszystkie specyfikacje mają status szkicu. [[http://pl.wikipedia.org/wiki/SPARQL | Źródło]] | |
| |
Zapytania buduje się podobnie jak w języku zapytań SQL z tą różnicą, że podaje się całą trójkę. | |
Zapytanie SPARQL dla podanego powyżej przykładu może wyglądać tak: | |
| |
<code> | |
SELECT ?x ?w ?q | |
WHERE {?x ?w ?q} | |
</code> | |
Oznacza to podgląd całej wiedzy, która jest zawarta w modelu. | |
| |
Ponieważ posłużyłem się językiem SPARQL na modelu rodziny, który został wcześniej już utworzony, wszelkie rezultaty będą przedstawione dla tych relacji. Na zapytanie takie uzyskałem odpowiedź: | |
<code> | |
Jasiu dziecko Jan | |
Jasiu dziecko Krystyna | |
Krystyna malzonek Jan | |
Jan malzonek Krystyna | |
Jan ojciec Jasiu | |
Jan ojciec Kasia | |
Kasia dziecko Jan | |
Kasia dziecko Krystyna | |
Kasia siostra Jasiu | |
</code> | |
| |
Jak widać są to wszytkie informacje, które zawarłem w modelu. (Dla czytelności zostały usunięte URI, aby odpowiedź nie wyglądała np. tak http://Family/KowalskiJan) | |
| |
Znając zasadę tworzenia zapytania, można otrzymać odpowiedź na "skomplikowane" zapytanie. | |
| |
| |
=====Termostat - RDF===== | |
| |
Aby stworzyć plik RDF reprezentujący model termostatu, najpierw utworzyłem model termostatu wg. wszystkich reguł. | |
| |
Aby plik taki został wygenerowany ścieżki do resoure'ów oraz propertis'ów muszą być unikalne stąd musiałem stworzyć dwa Stringi, którymi poprzedzałem każdy z nich. | |
<code> | |
static final String resourceUri = "http://Resource/my/"; | |
static final String propertyUri = "http://Property/my/"; | |
</code> | |
| |
| |
Tak zapisałem model w Javie: | |
<code> | |
Model model = ModelFactory.createDefaultModel(); | |
//1 | |
Resource day = model.createResource(resourceUri+ "Day"); | |
Resource workday = model.createResource(resourceUri+"Workday"); | |
Property monday = model.createProperty(propertyUri+"monday"); | |
Property tuesday = model.createProperty(propertyUri+"tuesday"); | |
Property wednesday = model.createProperty(propertyUri+"wednesday"); | |
Property thursday = model.createProperty(propertyUri+"thursday"); | |
Property friday = model.createProperty(propertyUri+"friday"); | |
day.addProperty(monday, workday); | |
day.addProperty(tuesday, workday); | |
day.addProperty(wednesday, workday); | |
day.addProperty(thursday, workday); | |
day.addProperty(friday, workday); | |
| |
//2 | |
Resource weekend = model.createResource(resourceUri + "Weekend"); | |
Property saturday = model.createProperty(propertyUri + "saturday"); | |
Property sunday = model.createProperty(propertyUri+ "sunday"); | |
day.addProperty(saturday, weekend); | |
day.addProperty(sunday, weekend); | |
| |
//3 4 5 | |
Resource time = model.createResource(resourceUri + "time"); | |
Resource hour = model.createResource(resourceUri + "hour"); | |
Property sevenAm = model.createProperty(propertyUri + "seven-before9am"); | |
Property sixPm = model.createProperty(propertyUri + "six-after5pm"); | |
Property noon = model.createProperty(propertyUri + "noon"); | |
time.addProperty(sevenAm, hour); | |
time.addProperty(sixPm, hour); | |
time.addProperty(noon, hour); | |
| |
//6 | |
//-- | |
| |
//7 | |
Resource month = model.createResource(resourceUri+ "month"); | |
Resource summer = model.createResource(resourceUri+"summer"); | |
Property january = model.createProperty(propertyUri+"january"); | |
Property february = model.createProperty(propertyUri+"february"); | |
Property december = model.createProperty(propertyUri+"december"); | |
month.addProperty(january, summer); | |
month.addProperty(february, summer); | |
month.addProperty(december, summer); | |
| |
//8 | |
Resource autumn = model.createResource(resourceUri+"autumn"); | |
Property march = model.createProperty(propertyUri+"march"); | |
Property april = model.createProperty(propertyUri+"april"); | |
Property may = model.createProperty(propertyUri+"may"); | |
month.addProperty(march, autumn); | |
month.addProperty(april, autumn); | |
month.addProperty(may, autumn); | |
| |
//9 | |
Resource winter = model.createResource(resourceUri+"winter"); | |
Property june = model.createProperty(propertyUri+"june"); | |
Property july = model.createProperty(propertyUri+"july"); | |
Property august = model.createProperty(propertyUri+"august"); | |
month.addProperty(june, winter); | |
month.addProperty(july, winter); | |
month.addProperty(august, winter); | |
| |
//10 | |
Resource spring = model.createResource(resourceUri+"spring"); | |
Property september = model.createProperty(propertyUri+"september"); | |
Property october = model.createProperty(propertyUri+"october"); | |
Property november = model.createProperty(propertyUri+"november"); | |
month.addProperty(september, spring); | |
month.addProperty(october, spring); | |
month.addProperty(november, spring); | |
| |
//11 12 13 | |
| |
| |
| |
Resource operation = model.createResource(resourceUri + "operation"); | |
Property businessHours = model.createProperty(propertyUri + "businessHours"); | |
Property notBusinessHours = model.createProperty(propertyUri + "notBusinessHours"); | |
operation.addProperty(businessHours, hour); | |
operation.addProperty(notBusinessHours, hour); | |
| |
//14 15 16 17 18 | |
Resource thermostat = model.createResource(resourceUri + "thermostat"); | |
Resource setting = model.createResource(resourceUri + "setting"); | |
Property degrees20 = model.createProperty(propertyUri + "20degrees"); | |
Property degrees15 = model.createProperty(propertyUri + "15degrees"); | |
Property degrees24 = model.createProperty(propertyUri + "24degrees"); | |
Property degrees27 = model.createProperty(propertyUri + "27degrees"); | |
Property degrees16 = model.createProperty(propertyUri + "16degrees"); | |
Property degrees18 = model.createProperty(propertyUri + "18degrees"); | |
Property degrees14 = model.createProperty(propertyUri + "14degrees"); | |
thermostat.addProperty(degrees20, setting); | |
thermostat.addProperty(degrees15, setting); | |
thermostat.addProperty(degrees24, setting); | |
thermostat.addProperty(degrees27, setting); | |
thermostat.addProperty(degrees16, setting); | |
thermostat.addProperty(degrees18, setting); | |
thermostat.addProperty(degrees14, setting); | |
</code> | |
| |
Na tej podstawie wygenerowałem plik RDF z zapisanym modelem: | |
<code xml> | |
<rdf:RDF | |
xmlns:j.0="http://Property/my/18" | |
xmlns:j.1="http://Property/my/" | |
xmlns:j.2="http://Property/my/15" | |
xmlns:j.3="http://Property/my/24" | |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |
xmlns:j.4="http://Property/my/27" | |
xmlns:j.5="http://Property/my/16" | |
xmlns:j.7="http://Property/my/14" | |
xmlns:j.6="http://Property/my/20" > | |
<rdf:Description rdf:about="http://Resource/my/time"> | |
<j.1:noon rdf:resource="http://Resource/my/hour"/> | |
<j.1:six-after5pm rdf:resource="http://Resource/my/hour"/> | |
<j.1:seven-before9am rdf:resource="http://Resource/my/hour"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/month"> | |
<j.1:january rdf:resource="http://Resource/my/summer"/> | |
<j.1:february rdf:resource="http://Resource/my/summer"/> | |
<j.1:september rdf:resource="http://Resource/my/spring"/> | |
<j.1:october rdf:resource="http://Resource/my/spring"/> | |
<j.1:july rdf:resource="http://Resource/my/winter"/> | |
<j.1:november rdf:resource="http://Resource/my/spring"/> | |
<j.1:may rdf:resource="http://Resource/my/autumn"/> | |
<j.1:april rdf:resource="http://Resource/my/autumn"/> | |
<j.1:august rdf:resource="http://Resource/my/winter"/> | |
<j.1:june rdf:resource="http://Resource/my/winter"/> | |
<j.1:december rdf:resource="http://Resource/my/summer"/> | |
<j.1:march rdf:resource="http://Resource/my/autumn"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/Day"> | |
<j.1:sunday rdf:resource="http://Resource/my/Weekend"/> | |
<j.1:saturday rdf:resource="http://Resource/my/Weekend"/> | |
<j.1:friday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:thursday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:wednesday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:tuesday rdf:resource="http://Resource/my/Workday"/> | |
<j.1:monday rdf:resource="http://Resource/my/Workday"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/operation"> | |
<j.1:notBusinessHours rdf:resource="http://Resource/my/hour"/> | |
<j.1:businessHours rdf:resource="http://Resource/my/hour"/> | |
</rdf:Description> | |
<rdf:Description rdf:about="http://Resource/my/thermostat"> | |
<j.7:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.0:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.5:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.4:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.3:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.2:degrees rdf:resource="http://Resource/my/setting"/> | |
<j.6:degrees rdf:resource="http://Resource/my/setting"/> | |
</rdf:Description> | |
</rdf:RDF> | |
| |
</code> | |
| |
| |
====== Dotychczasowy przebieg pracy ====== | |
Szcegóły pracy nad tym tematem można znaleźć [[pl:miw:miw08_ruleruntimej:przebieg_pracy| tutaj]] | |