Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:miw:miw08_ruleruntimej [2008/05/30 09:32] miw |
pl:miw:miw08_ruleruntimej [2019/06/27 15:50] (aktualna) |
====== Opis ====== | ====== Opis ====== |
| __**Projekt zakończony**__ |
| |
Realizujący: | Realizujący: |
**Marcin Gadamer** <marcin.gadamer@gmail.com> | **Marcin Gadamer** <marcin.gadamer@gmail.com> |
* output | * output |
How to integrate Prolog and Java in the best way regarding performance, and coding easiness + examples. | 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) | |
| |
| |
| |
| [[pl:miw:miw2008_tematy#ruleruntimej|MIW temat]] |
| |
| |